diff options
Diffstat (limited to 'src')
185 files changed, 47086 insertions, 21179 deletions
diff --git a/src/char/GNUmakefile b/src/char/GNUmakefile deleted file mode 100644 index f3164e0ec..000000000 --- a/src/char/GNUmakefile +++ /dev/null @@ -1,17 +0,0 @@ -all: char-server -txt: char-server - -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/lock.o ../common/malloc.o ../common/showmsg.o -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/lock.h ../common/timer.h ../common/malloc.h ../common/showmsg.h -char-server: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o $(COMMON_OBJ) - $(CC) -o ../../$@ $^ - -char.o: char.c char.h inter.h int_pet.h $(COMMON_H) ../common/version.h -inter.o: inter.c inter.h int_party.h int_guild.h int_storage.h int_pet.h char.h $(COMMON_H) -int_party.o: int_party.c int_party.h inter.h char.h $(COMMON_H) -int_guild.o: int_guild.c int_guild.h int_storage.h inter.h char.h $(COMMON_H) -int_storage.o: int_storage.c int_storage.h int_guild.h inter.h char.h $(COMMON_H) -int_pet.o: int_pet.c int_pet.h inter.h char.h $(COMMON_H) - -clean: - rm -f *.o ../../char-server diff --git a/src/char/Makefile b/src/char/Makefile index 0a2009333..aee0e69e2 100644 --- a/src/char/Makefile +++ b/src/char/Makefile @@ -1,10 +1,10 @@ all: char-server txt: char-server -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/lock.o ../common/malloc.o ../common/showmsg.o -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/lock.h ../common/timer.h ../common/malloc.h ../common/showmsg.h +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/lock.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o +COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/lock.h ../common/timer.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h char-server: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o $(COMMON_OBJ) - $(CC) -o ../../$@ $> + $(CC) -o ../../$@ $> $(LIB_S) char.o: char.c char.h inter.h int_pet.h $(COMMON_H) ../common/version.h inter.o: inter.c inter.h int_party.h int_guild.h int_storage.h int_pet.h char.h $(COMMON_H) diff --git a/src/char/char.c b/src/char/char.c index 7ad959bd8..73efbc864 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -2,29 +2,39 @@ // original : char2.c 2003/03/14 11:58:35 Rev.1.5 #include <sys/types.h> -#include <sys/socket.h> #include <stdio.h> #include <stdlib.h> + +#ifdef _WIN32 +#include <winsock.h> +typedef long in_addr_t; +#else +#include <sys/socket.h> #include <netinet/in.h> -#include <sys/time.h> -#include <time.h> +#include <arpa/inet.h> +#include <netdb.h> #include <sys/ioctl.h> +#include <sys/time.h> #include <unistd.h> +#endif + +#include <time.h> #include <signal.h> #include <fcntl.h> #include <string.h> -#include <arpa/inet.h> -#include <netdb.h> #include <stdarg.h> +#include "../common/strlib.h" #include "core.h" #include "socket.h" #include "timer.h" #include "mmo.h" +#include "db.h" #include "version.h" #include "lock.h" #include "char.h" #include "showmsg.h" +#include "buffer.h" #include "inter.h" #include "int_pet.h" @@ -38,9 +48,6 @@ struct mmo_map_server server[MAX_MAP_SERVERS]; int server_fd[MAX_MAP_SERVERS]; -int server_freezeflag[MAX_MAP_SERVERS]; // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed -int anti_freeze_enable = 0; -int ANTI_FREEZE_INTERVAL = 6; int login_fd, char_fd; char userid[24]; @@ -49,11 +56,13 @@ char server_name[20]; char wisp_server_name[24] = "Server"; int login_ip_set_ = 0; char login_ip_str[16]; -int login_ip; +in_addr_t login_ip; int login_port = 6900; int char_ip_set_ = 0; char char_ip_str[16]; -int char_ip; +int bind_ip_set_ = 0; +char bind_ip_str[16]; +in_addr_t char_ip; int char_port = 6121; int char_maintenance; int char_new; @@ -103,6 +112,7 @@ int char_id_count = 150000; struct mmo_charstatus *char_dat; int char_num, char_max; int max_connect_user = 0; +int gm_allow_level = 99; int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; int start_zeny = 500; int start_weapon = 1201; @@ -151,7 +161,7 @@ int char_log(char *fmt, ...) { fprintf(logfp, RETCODE); else { gettimeofday(&tv, NULL); - strftime(tmpstr, 24, "%d-%m-%Y %H:%M:%S", localtime(&(tv.tv_sec))); + strftime(tmpstr, 24, "%d-%m-%Y %H:%M:%S", localtime((const time_t*)&(tv.tv_sec))); sprintf(tmpstr + 19, ".%03d: %s", (int)tv.tv_usec / 1000, fmt); vfprintf(logfp, tmpstr, ap); } @@ -162,23 +172,6 @@ int char_log(char *fmt, ...) { return 0; } -//----------------------------------------------------- -// Function to suppress control characters in a string. -//----------------------------------------------------- -int remove_control_chars(unsigned char *str) { - int i; - int change = 0; - - for(i = 0; str[i]; i++) { - if (str[i] < 32) { - str[i] = '_'; - change = 1; - } - } - - return change; -} - //---------------------------------------------------------------------- // Determine if an account (id) is a GM account // and returns its level (or 0 if it isn't a GM account or if not found) @@ -235,6 +228,25 @@ char * search_character_name(int index) { return unknown_char_name; } +//------------------------------------------------- +// Set Character online/offline [Wizputer] +//------------------------------------------------- + +void set_char_online(int char_id, int account_id) { + if (login_fd <= 0 || session[login_fd]->eof) + return; + WFIFOW(login_fd,0) = 0x272b; + WFIFOL(login_fd,2) = account_id; + WFIFOSET(login_fd,6); +} +void set_char_offline(int char_id, int account_id) { + if (login_fd <= 0 || session[login_fd]->eof) + return; + WFIFOW(login_fd,0) = 0x272c; + WFIFOL(login_fd,2) = account_id; + WFIFOSET(login_fd,6); +} + /*--------------------------------------------------- Make a data line for friends list --------------------------------------------------*/ @@ -243,7 +255,7 @@ int mmo_friends_list_data_str(char *str, struct mmo_charstatus *p) { int i; char *str_p = str; str_p += sprintf(str_p, "%d", p->char_id); - + for (i=0;i<20;i++) { str_p += sprintf(str_p, ",%d,%s", p->friend_id[i],p->friend_name[i]); @@ -267,9 +279,9 @@ int mmo_char_tostr(char *str, struct mmo_charstatus *p) { str_p += sprintf(str_p, "%d\t%d,%d\t%s\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" - "\t%s,%d,%d\t%s,%d,%d,%d\t", + "\t%s,%d,%d\t%s,%d,%d,%d,%d,%d,%d\t", p->char_id, p->account_id, p->char_num, p->name, // - p->class, p->base_level, p->job_level, + p->class_, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, p->hp, p->max_hp, p->sp, p->max_sp, p->str, p->agi, p->vit, p->int_, p->dex, p->luk, @@ -280,7 +292,7 @@ int mmo_char_tostr(char *str, struct mmo_charstatus *p) { p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom, p->last_point.map, p->last_point.x, p->last_point.y, // p->save_point.map, p->save_point.x, p->save_point.y, - p->partner_id); + p->partner_id,p->father,p->mother,p->child); for(i = 0; i < 10; i++) if (p->memo_point[i].map[0]) { str_p += sprintf(str_p, "%s,%d,%d", p->memo_point[i].map, p->memo_point[i].x, p->memo_point[i].y); @@ -329,8 +341,28 @@ int mmo_char_fromstr(char *str, struct mmo_charstatus *p) { // initilialise character memset(p, '\0', sizeof(struct mmo_charstatus)); - - // If it's not char structure of version 1008 and after + + // If it's not char structure of version 1363 and after + if ((set = sscanf(str, "%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" + "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" + "\t%[^,],%d,%d\t%[^,],%d,%d,%d,%d,%d,%d%n", + &tmp_int[0], &tmp_int[1], &tmp_int[2], p->name, // + &tmp_int[3], &tmp_int[4], &tmp_int[5], + &tmp_int[6], &tmp_int[7], &tmp_int[8], + &tmp_int[9], &tmp_int[10], &tmp_int[11], &tmp_int[12], + &tmp_int[13], &tmp_int[14], &tmp_int[15], &tmp_int[16], &tmp_int[17], &tmp_int[18], + &tmp_int[19], &tmp_int[20], + &tmp_int[21], &tmp_int[22], &tmp_int[23], // + &tmp_int[24], &tmp_int[25], &tmp_int[26], + &tmp_int[27], &tmp_int[28], &tmp_int[29], + &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34], + p->last_point.map, &tmp_int[35], &tmp_int[36], // + p->save_point.map, &tmp_int[37], &tmp_int[38], &tmp_int[39], + &tmp_int[40], &tmp_int[41], &tmp_int[42], &next)) != 46) { + tmp_int[40] = 0; // father + tmp_int[41] = 0; // mother + tmp_int[42] = 0; // child + // If it's not char structure of version 1008 and before 1363 if ((set = sscanf(str, "%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%[^,],%d,%d\t%[^,],%d,%d,%d%n", @@ -389,15 +421,20 @@ int mmo_char_fromstr(char *str, struct mmo_charstatus *p) { } // Char structure of version 1008+ } else { + set+=3; //printf("char: new char data ver.3\n"); } - if (set != 43) + // Char structture of version 1363+ + } else { + //printf("char: new char data ver.4\n"); + } + if (set != 46) return 0; p->char_id = tmp_int[0]; p->account_id = tmp_int[1]; p->char_num = tmp_int[2]; - p->class = tmp_int[3]; + p->class_ = tmp_int[3]; p->base_level = tmp_int[4]; p->job_level = tmp_int[5]; p->base_exp = tmp_int[6]; @@ -434,6 +471,9 @@ int mmo_char_fromstr(char *str, struct mmo_charstatus *p) { p->save_point.x = tmp_int[37]; p->save_point.y = tmp_int[38]; p->partner_id = tmp_int[39]; + p->father = tmp_int[40]; + p->mother = tmp_int[41]; + p->child = tmp_int[42]; // Some checks for(i = 0; i < char_num; i++) { @@ -574,13 +614,16 @@ int parse_friend_txt(struct mmo_charstatus *p) char line[1024]; int i,cid=0,temp[20]; FILE *fp; - + // Open the file and look for the ID fp = fopen(friends_txt, "r"); - + + if(fp == NULL) + return 1; + while(fgets(line, sizeof(line)-1, fp)) { - + if(line[0] == '/' && line[1] == '/') continue; @@ -608,7 +651,7 @@ int parse_friend_txt(struct mmo_charstatus *p) if (cid == p->char_id) break; } - + // No register of friends list if (cid == 0) { fclose(fp); @@ -634,16 +677,11 @@ int mmo_char_init(void) { FILE *fp; char_max = 256; - char_dat = calloc(sizeof(struct mmo_charstatus) * 256, 1); + char_dat = (struct mmo_charstatus*)aCalloc(sizeof(struct mmo_charstatus) * 256, 1); if (!char_dat) { printf("out of memory: mmo_char_init (calloc of char_dat).\n"); exit(1); } - online_chars = calloc(sizeof(struct online_chars) * 256, 1); - if (!online_chars) { - printf("out of memory: mmo_char_init (calloc of online_chars).\n"); - exit(1); - } for(i = 0; i < char_max; i++) { online_chars[i].char_id = -1; @@ -679,13 +717,13 @@ int mmo_char_init(void) { if (char_num >= char_max) { char_max += 256; - char_dat = realloc(char_dat, sizeof(struct mmo_charstatus) * char_max); + char_dat = (struct mmo_charstatus*)aRealloc(char_dat, sizeof(struct mmo_charstatus) * char_max); if (!char_dat) { printf("Out of memory: mmo_char_init (realloc of char_dat).\n"); char_log("Out of memory: mmo_char_init (realloc of char_dat)." RETCODE); exit(1); } - online_chars = realloc(online_chars, sizeof(struct online_chars) * char_max); + online_chars = (struct online_chars*)aRealloc(online_chars, sizeof(struct online_chars) * char_max); if (!online_chars) { printf("Out of memory: mmo_char_init (realloc of online_chars).\n"); char_log("Out of memory: mmo_char_init (realloc of online_chars)." RETCODE); @@ -699,10 +737,10 @@ int mmo_char_init(void) { } ret = mmo_char_fromstr(line, &char_dat[char_num]); - + // Initialize friends list parse_friend_txt(&char_dat[char_num]); // Grab friends for the character - + if (ret > 0) { // negative value or zero for errors if (char_dat[char_num].char_id >= char_id_count) char_id_count = char_dat[char_num].char_id + 1; @@ -765,7 +803,8 @@ void mmo_char_sync(void) { int i, j, k; int lock; FILE *fp,*f_fp; - int id[char_num]; + //int *id = (int *) aMalloc(sizeof(int) * char_num); + CREATE_BUFFER(id, int, char_num); // Sorting before save (by [Yor]) for(i = 0; i < char_num; i++) { @@ -804,6 +843,8 @@ void mmo_char_sync(void) { if (fp == NULL) { printf("WARNING: Server can't not create backup of characters file.\n"); char_log("WARNING: Server can't not create backup of characters file." RETCODE); + //aFree(id); // free up the memory before leaving -.- [Ajarn] + DELETE_BUFFER(id); return; } for(i = 0; i < char_num; i++) { @@ -821,9 +862,12 @@ void mmo_char_sync(void) { mmo_friends_list_data_str(f_line, &char_dat[id[i]]); fprintf(f_fp, "%s" RETCODE, f_line); } - + lock_fclose(f_fp, friends_txt, &lock); - + + //aFree(id); + DELETE_BUFFER(id); + return; } @@ -843,18 +887,18 @@ int make_new_char(int fd, unsigned char *dat) { int i, j; struct char_session_data *sd; - sd = session[fd]->session_data; + sd = (struct char_session_data*)session[fd]->session_data; // remove control characters from the name dat[23] = '\0'; - if (remove_control_chars(dat)) { + if (remove_control_chars((unsigned char *)(char*)dat)) { char_log("Make new char error (control char received in the name): (connection #%d, account: %d)." RETCODE, fd, sd->account_id); return -1; } // check lenght of character name - if (strlen(dat) < 4) { + if (strlen((const char*)dat) < 4) { char_log("Make new char error (character name too small): (connection #%d, account: %d, name: '%s')." RETCODE, fd, sd->account_id, dat); return -1; @@ -896,8 +940,8 @@ int make_new_char(int fd, unsigned char *dat) { } for(i = 0; i < char_num; i++) { - if ((name_ignoring_case != 0 && strcmp(char_dat[i].name, dat) == 0) || - (name_ignoring_case == 0 && strcmpi(char_dat[i].name, dat) == 0)) { + if ((name_ignoring_case != 0 && strcmp(char_dat[i].name, (const char*)dat) == 0) || + (name_ignoring_case == 0 && strcmpi(char_dat[i].name, (const char*)dat) == 0)) { char_log("Make new char error (name already exists): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %d), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d." RETCODE, fd, sd->account_id, dat[30], dat, char_dat[i].name, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29], dat[33], dat[31]); return -1; @@ -909,7 +953,7 @@ int make_new_char(int fd, unsigned char *dat) { } } - if (strcmp(wisp_server_name, dat) == 0) { + if (strcmp(wisp_server_name, (const char*)dat) == 0) { char_log("Make new char error (name used is wisp name for server): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %d), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d." RETCODE, fd, sd->account_id, dat[30], dat, char_dat[i].name, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29], dat[33], dat[31]); return -1; @@ -917,13 +961,13 @@ int make_new_char(int fd, unsigned char *dat) { if (char_num >= char_max) { char_max += 256; - char_dat = realloc(char_dat, sizeof(struct mmo_charstatus) * char_max); + char_dat = (struct mmo_charstatus*)aRealloc(char_dat, sizeof(struct mmo_charstatus) * char_max); if (!char_dat) { printf("Out of memory: make_new_char (realloc of char_dat).\n"); char_log("Out of memory: make_new_char (realloc of char_dat)." RETCODE); exit(1); } - online_chars = realloc(online_chars, sizeof(struct online_chars) * char_max); + online_chars = (struct online_chars*)aRealloc(online_chars, sizeof(struct online_chars) * char_max); if (!online_chars) { printf("Out of memory: make_new_char (realloc of online_chars).\n"); char_log("Out of memory: make_new_char (realloc of online_chars)." RETCODE); @@ -943,8 +987,8 @@ int make_new_char(int fd, unsigned char *dat) { char_dat[i].char_id = char_id_count++; char_dat[i].account_id = sd->account_id; char_dat[i].char_num = dat[30]; - strcpy(char_dat[i].name, dat); - char_dat[i].class = 0; + strcpy(char_dat[i].name, (const char*)dat); + char_dat[i].class_ = 0; char_dat[i].base_level = 1; char_dat[i].job_level = 1; char_dat[i].base_exp = 0; @@ -994,8 +1038,8 @@ int make_new_char(int fd, unsigned char *dat) { //---------------------------------------------------- // This function return the name of the job (by [Yor]) //---------------------------------------------------- -char * job_name(int class) { - switch (class) { +char * job_name(int class_) { + switch (class_) { case 0: return "Novice"; case 1: return "Swordsman"; case 2: return "Mage"; @@ -1080,7 +1124,7 @@ void create_online_files(void) { char temp[256]; // to prepare what we must display time_t time_server; // for number of seconds struct tm *datetime; // variable for time in structure ->tm_mday, ->tm_sec, ... - int id[online_players_max]; + int id[4096]; // don't return here if we display nothing, because server[j].users is updated in the first loop. @@ -1153,12 +1197,12 @@ void create_online_files(void) { break; case 4: // by job (and job level) for(k = 0; k < players; k++) - if (char_dat[j].class < char_dat[id[k]].class || + if (char_dat[j].class_ < char_dat[id[k]].class_ || // if same job, we sort by job level. - (char_dat[j].class == char_dat[id[k]].class && + (char_dat[j].class_ == char_dat[id[k]].class_ && char_dat[j].job_level < char_dat[id[k]].job_level) || // if same job and job level, we sort by job exp. - (char_dat[j].class == char_dat[id[k]].class && + (char_dat[j].class_ == char_dat[id[k]].class_ && char_dat[j].job_level == char_dat[id[k]].job_level && char_dat[j].job_exp < char_dat[id[k]].job_exp)) { for(l = players; l > k; l--) @@ -1299,7 +1343,7 @@ void create_online_files(void) { } // displaying of the job if (online_display_option & 6) { - char * jobname = job_name(char_dat[j].class); + char * jobname = job_name(char_dat[j].class_); if ((online_display_option & 6) == 6) { fprintf(fp2, " <td>%s %d/%d</td>\n", jobname, char_dat[j].base_level, char_dat[j].job_level); fprintf(fp, "%-18s %3d/%3d ", jobname, char_dat[j].base_level, char_dat[j].job_level); @@ -1352,8 +1396,9 @@ void create_online_files(void) { if (players == 0) { fprintf(fp2, " <p>No user is online.</p>\n"); fprintf(fp, "No user is online.\n"); - // no display if only 1 player } else if (players == 1) { + fprintf(fp2, " <p>%d user is online.</p>\n", players); + fprintf(fp, "%d user is online.\n", players); } else { fprintf(fp2, " <p>%d users are online.</p>\n", players); fprintf(fp, "%d users are online.\n", players); @@ -1433,9 +1478,15 @@ int mmo_char_send006b(int fd, struct char_session_data *sd) { WFIFOW(fd,j+46) = (p->sp > 0x7fff) ? 0x7fff : p->sp; WFIFOW(fd,j+48) = (p->max_sp > 0x7fff) ? 0x7fff : p->max_sp; WFIFOW(fd,j+50) = DEFAULT_WALK_SPEED; // p->speed; - WFIFOW(fd,j+52) = p->class; + WFIFOW(fd,j+52) = p->class_; WFIFOW(fd,j+54) = p->hair; - WFIFOW(fd,j+56) = p->weapon; + + // pecopeco knights/crusaders crash fix + if (p->class_ == 13 || p->class_ == 21 || + p->class_ == 4014 || p->class_ == 4022) + WFIFOW(fd,j+56) = 0; + else WFIFOW(fd,j+56) = p->weapon; + WFIFOW(fd,j+58) = p->base_level; WFIFOW(fd,j+60) = p->skill_point; WFIFOW(fd,j+62) = p->head_bottom; @@ -1501,9 +1552,9 @@ int char_divorce(struct mmo_charstatus *cs) { //------------------------------------------------------------ // E-mail check: return 0 (not correct) or 1 (valid). by [Yor] //------------------------------------------------------------ -int e_mail_check(unsigned char *email) { +int e_mail_check(char *email) { char ch; - unsigned char* last_arobas; + char* last_arobas; // athena limits if (strlen(email) < 3 || strlen(email) > 39) @@ -1546,7 +1597,7 @@ int disconnect_player(int accound_id) { // disconnect player if online on char-server for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data)) { + if (session[i] && (sd = (struct char_session_data*)session[i]->session_data)) { if (sd->account_id == accound_id) { session[i]->eof = 1; return 1; @@ -1579,7 +1630,7 @@ static int char_delete(struct mmo_charstatus *cs) { // —£¥ if (cs->partner_id){ // —£¥î•ñ‚ðmap‚É’Ê’m - char buf[10]; + unsigned char buf[10]; WBUFW(buf,0) = 0x2b12; WBUFL(buf,2) = cs->char_id; WBUFL(buf,6) = cs->partner_id; @@ -1608,7 +1659,7 @@ int parse_tologin(int fd) { return 0; } - sd = session[fd]->session_data; + sd = (struct char_session_data*)session[fd]->session_data; while(RFIFOREST(fd) >= 2) { // printf("parse_tologin: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd)); @@ -1641,7 +1692,7 @@ int parse_tologin(int fd) { return 0; // printf("parse_tologin 2713 : %d\n", RFIFOB(fd,6)); for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data) && sd->account_id == RFIFOL(fd,2)) { + if (session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->account_id == RFIFOL(fd,2)) { if (RFIFOB(fd,6) != 0) { WFIFOW(i,0) = 0x6c; WFIFOB(i,2) = 0x42; @@ -1657,6 +1708,10 @@ int parse_tologin(int fd) { sd->connect_until_time = (time_t)RFIFOL(fd,47); // send characters to player mmo_char_send006b(i, sd); + } else if(isGM(sd->account_id) >= gm_allow_level) { + sd->connect_until_time = (time_t)RFIFOL(fd,47); + // send characters to player + mmo_char_send006b(i, sd); } else { // refuse connection: too much online players // printf("count_users(): %d < max_connect_use (%d) -> fail...\n", count_users(), max_connect_user); @@ -1675,7 +1730,7 @@ int parse_tologin(int fd) { if (RFIFOREST(fd) < 50) return 0; for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data)) { + if (session[i] && (sd = (struct char_session_data*)session[i]->session_data)) { if (sd->account_id == RFIFOL(fd,2)) { memcpy(sd->email, RFIFOP(fd,6), 40); if (e_mail_check(sd->email) == 0) @@ -1688,6 +1743,42 @@ int parse_tologin(int fd) { RFIFOSKIP(fd,50); break; + // login-server alive packet + case 0x2718: + if (RFIFOREST(fd) < 2) + return 0; + RFIFOSKIP(fd,2); + break; + + // Receiving authentification from Freya-type login server (to avoid char->login->char) + case 0x2719: + if (RFIFOREST(fd) < 18) + return 0; + // to conserv a maximum of authentification, search if account is already authentified and replace it + // that will reduce multiple connection too + for(i = 0; i < AUTH_FIFO_SIZE; i++) + if (auth_fifo[i].account_id == RFIFOL(fd,2)) + break; + // if not found, use next value + if (i == AUTH_FIFO_SIZE) { + if (auth_fifo_pos >= AUTH_FIFO_SIZE) + auth_fifo_pos = 0; + i = auth_fifo_pos; + auth_fifo_pos++; + } + //printf("auth_fifo set (auth #%d) - account: %d, secure: %08x-%08x\n", i, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); + auth_fifo[i].account_id = RFIFOL(fd,2); + auth_fifo[i].char_id = 0; + auth_fifo[i].login_id1 = RFIFOL(fd,6); + auth_fifo[i].login_id2 = RFIFOL(fd,10); + auth_fifo[i].delflag = 2; // 0: auth_fifo canceled/void, 2: auth_fifo received from login/map server in memory, 1: connection authentified + auth_fifo[i].char_pos = 0; + auth_fifo[i].connect_until_time = 0; // unlimited/unknown time by default (not display in map-server) + auth_fifo[i].ip = RFIFOL(fd,14); + //auth_fifo[i].map_auth = 0; + RFIFOSKIP(fd,18); + break; + case 0x2721: // gm reply if (RFIFOREST(fd) < 10) return 0; @@ -1714,7 +1805,7 @@ int parse_tologin(int fd) { if (acc > 0) { for (i = 0; i < char_num; i++) { if (char_dat[i].account_id == acc) { - int jobclass = char_dat[i].class; + int jobclass = char_dat[i].class_; char_dat[i].sex = sex; auth_fifo[i].sex = sex; if (jobclass == 19 || jobclass == 20 || @@ -1722,11 +1813,11 @@ int parse_tologin(int fd) { jobclass == 4042 || jobclass == 4043) { // job modification if (jobclass == 19 || jobclass == 20) { - char_dat[i].class = (sex) ? 19 : 20; + char_dat[i].class_ = (sex) ? 19 : 20; } else if (jobclass == 4020 || jobclass == 4021) { - char_dat[i].class = (sex) ? 4020 : 4021; + char_dat[i].class_ = (sex) ? 4020 : 4021; } else if (jobclass == 4042 || jobclass == 4043) { - char_dat[i].class = (sex) ? 4042 : 4043; + char_dat[i].class_ = (sex) ? 4042 : 4043; } // remove specifical skills of classes 19, 4020 and 4042 for(j = 315; j <= 322; j++) { @@ -1780,14 +1871,14 @@ int parse_tologin(int fd) { if (i == MAX_MAP_SERVERS) char_log("'ladmin': Receiving a message for broadcast, but no map-server is online." RETCODE); else { - char buf[128]; - char message[RFIFOL(fd,4) + 1]; // +1 to add a null terminated if not exist in the packet + unsigned char buf[128]; + char message[4096]; // +1 to add a null terminated if not exist in the packet int lp; char *p; memset(message, '\0', sizeof(message)); memcpy(message, RFIFOP(fd,8), RFIFOL(fd,4)); message[sizeof(message)-1] = '\0'; - remove_control_chars(message); + remove_control_chars((unsigned char *)message); // remove all first spaces p = message; while(p[0] == ' ') @@ -1875,7 +1966,7 @@ int parse_tologin(int fd) { int j, k; struct char_session_data *sd2; for (j = 0; j < fd_max; j++) { - if (session[j] && (sd2 = session[j]->session_data) && + if (session[j] && (sd2 = (struct char_session_data*)session[j]->session_data) && sd2->account_id == char_dat[char_num-1].account_id) { for (k = 0; k < 9; k++) { if (sd2->found_char[k] == char_num-1) { @@ -1928,10 +2019,10 @@ int parse_tologin(int fd) { if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; { - char buf[32000]; + unsigned char buf[32000]; if (gm_account != NULL) - free(gm_account); - gm_account = calloc(sizeof(struct gm_account) * ((RFIFOW(fd,2) - 4) / 5), 1); + aFree(gm_account); + gm_account = (struct gm_account*)aCalloc(sizeof(struct gm_account) * ((RFIFOW(fd,2) - 4) / 5), 1); GM_num = 0; for (i = 4; i < RFIFOW(fd,2); i = i + 5) { gm_account[GM_num].account_id = RFIFOL(fd,i); @@ -1950,7 +2041,66 @@ int parse_tologin(int fd) { RFIFOSKIP(fd,RFIFOW(fd,2)); break; + // Receive GM accounts [Freya login server packet by Yor] + case 0x2733: + // add test here to remember that the login-server is Freya-type + // sprintf (login_server_type, "Freya"); + if (RFIFOREST(fd) < 7) + return 0; + { + unsigned char buf[32000]; + int new_level = 0; + for(i = 0; i < GM_num; i++) + if (gm_account[i].account_id == RFIFOL(fd,2)) { + if (gm_account[i].level != (int)RFIFOB(fd,6)) { + gm_account[i].level = (int)RFIFOB(fd,6); + new_level = 1; + } + break; + } + // if not found, add it + if (i == GM_num) { + // limited to 4000, because we send information to char-servers (more than 4000 GM accounts???) + // int (id) + int (level) = 8 bytes * 4000 = 32k (limit of packets in windows) + if (((int)RFIFOB(fd,6)) > 0 && GM_num < 4000) { + if (GM_num == 0) { + gm_account = (struct gm_account*)aMalloc(sizeof(struct gm_account)); + } else { + gm_account = (struct gm_account*)aRealloc(gm_account, sizeof(struct gm_account) * (GM_num + 1)); + } + gm_account[GM_num].account_id = RFIFOL(fd,2); + gm_account[GM_num].level = (int)RFIFOB(fd,6); + new_level = 1; + GM_num++; + if (GM_num >= 4000) { + printf("***WARNING: 4000 GM accounts found. Next GM accounts are not readed.\n"); + char_log("***WARNING: 4000 GM accounts found. Next GM accounts are not readed." RETCODE); + } + } + } + if (new_level == 1) { + int len; + printf("From login-server: receiving a GM account information (%d: level %d).\n", RFIFOL(fd,2), (int)RFIFOB(fd,6)); + char_log("From login-server: receiving a GM account information (%d: level %d)." RETCODE, RFIFOL(fd,2), (int)RFIFOB(fd,6)); + //create_online_files(); // not change online file for only 1 player (in next timer, that will be done + // send gm acccounts level to map-servers + len = 4; + WBUFW(buf,0) = 0x2b15; + + for(i = 0; i < GM_num; i++) { + WBUFL(buf, len) = gm_account[i].account_id; + WBUFB(buf, len+4) = (unsigned char)gm_account[i].level; + len += 5; + } + WBUFW(buf, 2) = len; + mapif_sendall(buf, len); + } + } + RFIFOSKIP(fd,7); + break; + default: + printf("parse_tologin: unknown packet %x! \n", RFIFOW(fd,0)); session[fd]->eof = 1; return 0; } @@ -1960,28 +2110,6 @@ int parse_tologin(int fd) { return 0; } -//-------------------------------- -// Map-server anti-freeze system -//-------------------------------- -int map_anti_freeze_system(int tid, unsigned int tick, int id, int data) { - int i; - - //printf("Entering in map_anti_freeze_system function to check freeze of servers.\n"); - for(i = 0; i < MAX_MAP_SERVERS; i++) { - if (server_fd[i] >= 0) {// if map-server is online - //printf("map_anti_freeze_system: server #%d, flag: %d.\n", i, server_freezeflag[i]); - if (server_freezeflag[i]-- < 1) { // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed - printf("Map-server anti-freeze system: char-server #%d is freezed -> disconnection.\n", i); - char_log("Map-server anti-freeze system: char-server #%d is freezed -> disconnection." RETCODE, - i); - session[server_fd[i]]->eof = 1; - } - } - } - - return 0; -} - int parse_frommap(int fd) { int i, j; int id; @@ -2007,6 +2135,14 @@ int parse_frommap(int fd) { // printf("parse_frommap: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd)); switch(RFIFOW(fd,0)) { + + // map-server alive packet + case 0x2718: + if (RFIFOREST(fd) < 2) + return 0; + RFIFOSKIP(fd,2); + break; + // request from map-server to reload GM accounts. Transmission to login-server (by Yor) case 0x2af7: if (login_fd > 0) { // don't send request if no login-server @@ -2119,8 +2255,6 @@ int parse_frommap(int fd) { if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; server[id].users = RFIFOW(fd,4); - if(anti_freeze_enable) - server_freezeflag[id] = 5; // Map anti-freeze system. Counter. 5 ok, 4...0 freezed // remove all previously online players of the server for(i = 0; i < online_players_max; i++) if (online_chars[i].server == id) { @@ -2141,7 +2275,7 @@ int parse_frommap(int fd) { if (j == online_players_max) { // create 256 new slots online_players_max += 256; - online_chars = realloc(online_chars, sizeof(struct online_chars) * online_players_max); + online_chars = (struct online_chars*)aRealloc(online_chars, sizeof(struct online_chars) * online_players_max); if (!online_chars) { printf("out of memory: parse_frommap - online_chars (realloc).\n"); exit(1); @@ -2411,20 +2545,23 @@ int parse_frommap(int fd) { RFIFOSKIP(fd, RFIFOW(fd,2)); // printf("char: save_account_reg (from map)\n"); break; - } - // Map server send information to change an email of an account -> login-server - case 0x3000: - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + } + // Character disconnected set online 0 [Wizputer] + case 0x2b17: + if (RFIFOREST(fd) < 6) return 0; - if (login_fd > 0) { // don't send request if no login-server - WFIFOW(login_fd,0) = 0x3000; - WFIFOW(login_fd,2) = RFIFOW(fd,2); - WFIFOL(login_fd,4) = RFIFOL(fd,4); - WFIFOB(login_fd,8) = RFIFOB(fd,8); - WFIFOSET(login_fd, RFIFOW(fd,2)); - printf("char : change sex -> login %d %d %d \n", RFIFOL(fd,4), RFIFOB(fd,8), RFIFOW(fd,2)); - } - RFIFOSKIP(fd, RFIFOW(fd,2)); + //printf("Setting %d char offline\n",RFIFOL(fd,2)); + set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6)); + RFIFOSKIP(fd,10); + break; + + // Character set online [Wizputer] + case 0x2b19: + if (RFIFOREST(fd) < 6) + return 0; + //printf("Setting %d char online\n",RFIFOL(fd,2)); + set_char_online(RFIFOL(fd,2),RFIFOL(fd,6)); + RFIFOSKIP(fd,10); break; default: @@ -2513,7 +2650,7 @@ int parse_char(int fd) { return 0; } - sd = session[fd]->session_data; + sd = (struct char_session_data*)session[fd]->session_data; while (RFIFOREST(fd) >= 2) { cmd = RFIFOW(fd,0); @@ -2537,7 +2674,7 @@ int parse_char(int fd) { // if (sd == NULL && cmd != 0x65 && cmd != 0x20b && cmd != 0x187 && // cmd != 0x2af8 && cmd != 0x7530 && cmd != 0x7532) // cmd = 0xffff; // ƒpƒPƒbƒgƒ_ƒ“ƒv‚ð•\ަ‚³‚¹‚é - + switch(cmd){ case 0x20b: //20040622ˆÃ†‰»ragexe‘Ήž if (RFIFOREST(fd) < 19) @@ -2555,7 +2692,9 @@ int parse_char(int fd) { else printf("Account Logged On; Account ID: %d.\n", RFIFOL(fd,2)); if (sd == NULL) { - sd = session[fd]->session_data = calloc(sizeof(struct char_session_data), 1); + sd = (struct char_session_data*)aCalloc(sizeof(struct char_session_data), 1); + session[fd]->session_data = sd; + memset(sd, 0, sizeof(struct char_session_data)); memcpy(sd->email, "no mail", 40); // put here a mail without '@' to refuse deletion if we don't receive the e-mail sd->connect_until_time = 0; // unknow or illimited (not displaying on map-server) @@ -2742,7 +2881,7 @@ int parse_char(int fd) { WFIFOW(fd,2+46) = (char_dat[i].sp > 0x7fff) ? 0x7fff : char_dat[i].sp; WFIFOW(fd,2+48) = (char_dat[i].max_sp > 0x7fff) ? 0x7fff : char_dat[i].max_sp; WFIFOW(fd,2+50) = DEFAULT_WALK_SPEED; // char_dat[i].speed; - WFIFOW(fd,2+52) = char_dat[i].class; + WFIFOW(fd,2+52) = char_dat[i].class_; WFIFOW(fd,2+54) = char_dat[i].hair; WFIFOW(fd,2+58) = char_dat[i].base_level; @@ -2835,7 +2974,7 @@ int parse_char(int fd) { int j, k; struct char_session_data *sd2; for (j = 0; j < fd_max; j++) { - if (session[j] && (sd2 = session[j]->session_data) && + if (session[j] && (sd2 = (struct char_session_data*)session[j]->session_data) && sd2->account_id == char_dat[char_num-1].account_id) { for (k = 0; k < 9; k++) { if (sd2->found_char[k] == char_num-1) { @@ -2877,7 +3016,7 @@ int parse_char(int fd) { if (server_fd[i] < 0) break; } - if (i == MAX_MAP_SERVERS || strcmp(RFIFOP(fd,2), userid) || strcmp(RFIFOP(fd,26), passwd)){ + if (i == MAX_MAP_SERVERS || strcmp((char*)RFIFOP(fd,2), userid) || strcmp((char*)RFIFOP(fd,26), passwd)){ WFIFOB(fd,2) = 3; WFIFOSET(fd,3); RFIFOSKIP(fd,60); @@ -2886,8 +3025,6 @@ int parse_char(int fd) { WFIFOB(fd,2) = 0; session[fd]->func_parse = parse_frommap; server_fd[i] = fd; - if(anti_freeze_enable) - server_freezeflag[i] = 5; // Map anti-freeze system. Counter. 5 ok, 4...0 freezed server[i].ip = RFIFOL(fd,54); server[i].port = RFIFOW(fd,58); server[i].users = 0; @@ -2945,24 +3082,24 @@ int parse_char(int fd) { // Console Command Parser [Wizputer] int parse_console(char *buf) { char *type,*command; - - type = (char *)malloc(64); - command = (char *)malloc(64); - + + type = (char *)aMalloc(64); + command = (char *)aMalloc(64); + memset(type,0,64); memset(command,0,64); - + printf("Console: %s\n",buf); - + if ( sscanf(buf, "%[^:]:%[^\n]", type , command ) < 2 ) sscanf(buf,"%[^\n]",type); - + printf("Type of command: %s || Command: %s \n",type,command); - - if(buf) free(buf); - if(type) free(type); - if(command) free(command); - + + if(buf) aFree(buf); + if(type) aFree(type); + if(command) aFree(command); + return 0; } @@ -3015,7 +3152,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len) { int send_users_tologin(int tid, unsigned int tick, int id, int data) { int users = count_users(); - char buf[16]; + unsigned char buf[16]; if (login_fd > 0 && session[login_fd]) { // send number of user to login server @@ -3103,8 +3240,8 @@ int lan_config_read(const char *lancfgName) { if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2) continue; - remove_control_chars(w1); - remove_control_chars(w2); + remove_control_chars((unsigned char *)w1); + remove_control_chars((unsigned char *)w2); if (strcmpi(w1, "lan_map_ip") == 0) { // Read map-server Lan IP Address h = gethostbyname(w2); if (h != NULL) { @@ -3175,8 +3312,8 @@ int char_config_read(const char *cfgName) { if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2) continue; - remove_control_chars(w1); - remove_control_chars(w2); + remove_control_chars((unsigned char *)w1); + remove_control_chars((unsigned char *)w2); if (strcmpi(w1, "userid") == 0) { memcpy(userid, w2, 24); } else if (strcmpi(w1, "passwd") == 0) { @@ -3184,7 +3321,7 @@ int char_config_read(const char *cfgName) { } else if (strcmpi(w1, "server_name") == 0) { memcpy(server_name, w2, sizeof(server_name)); server_name[sizeof(server_name) - 1] = '\0'; - printf("%s server has been intialized\n", w2); + printf("%s server has been initialized\n", w2); } else if (strcmpi(w1, "wisp_server_name") == 0) { if (strlen(w2) >= 4) { memcpy(wisp_server_name, w2, sizeof(wisp_server_name)); @@ -3208,6 +3345,14 @@ int char_config_read(const char *cfgName) { sprintf(char_ip_str, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); } else memcpy(char_ip_str, w2, 16); + } else if (strcmpi(w1, "bind_ip") == 0) { + bind_ip_set_ = 1; + h = gethostbyname(w2); + if (h != NULL) { + printf("Character server binding IP address : %s -> %d.%d.%d.%d\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + sprintf(bind_ip_str, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + } else + memcpy(bind_ip_str, w2, 16); } else if (strcmpi(w1, "char_port") == 0) { char_port = atoi(w2); } else if (strcmpi(w1, "char_maintenance") == 0) { @@ -3228,6 +3373,10 @@ int char_config_read(const char *cfgName) { max_connect_user = atoi(w2); if (max_connect_user < 0) max_connect_user = 0; // unlimited online players + } else if(strcmpi(w1, "gm_allow_level") == 0) { + gm_allow_level = atoi(w2); + if(gm_allow_level < 0) + gm_allow_level = 99; } else if (strcmpi(w1, "check_ip_flag") == 0) { check_ip_flag = config_switch(w2); } else if (strcmpi(w1, "autosave_time") == 0) { @@ -3296,12 +3445,6 @@ int char_config_read(const char *cfgName) { online_refresh_html = 1; } else if(strcmpi(w1,"db_path")==0) { strcpy(db_path,w2); - } else if(strcmpi(w1,"anti_freeze_enable")==0){ - anti_freeze_enable = config_switch(w2); - } else if (strcmpi(w1, "anti_freeze_interval") == 0) { - ANTI_FREEZE_INTERVAL = atoi(w2); - if (ANTI_FREEZE_INTERVAL < 5) - ANTI_FREEZE_INTERVAL = 5; // minimum 5 seconds } else if (strcmpi(w1, "import") == 0) { char_config_read(w2); } else if (strcmpi(w1, "console") == 0) { @@ -3343,19 +3486,20 @@ void do_final(void) { } create_online_files(); - if(online_chars) free(online_chars); + if(online_chars) aFree(online_chars); mmo_char_sync(); inter_save(); - if(gm_account) free(gm_account); - if(char_dat) free(char_dat); + if(gm_account) aFree(gm_account); + if(char_dat) aFree(char_dat); delete_session(login_fd); delete_session(char_fd); - for(i = 0; i < fd_max; i++) - if(session[i] != NULL) free(session[i]); + inter_final(); + exit_dbn(); + timer_final(); char_log("----End of char-server (normal end with closing of all files)." RETCODE); } @@ -3363,21 +3507,23 @@ void do_final(void) { int do_init(int argc, char **argv) { int i; - // a newline in the log... - char_log(""); - char_log("The char-server starting..." RETCODE); - + SERVER_TYPE = SERVER_CHAR; char_config_read((argc < 2) ? CHAR_CONF_NAME : argv[1]); lan_config_read((argc > 1) ? argv[1] : LOGIN_LAN_CONF_NAME); - if ((naddr_ != 0) && (login_ip_set_ == 0 || char_ip_set_ == 0)) { + // a newline in the log... + char_log(""); + // moved behind char_config_read in case we changed the filename [celest] + char_log("The char-server starting..." RETCODE); + + if ((naddr_ != 0) && (login_ip_set_ == 0 || char_ip_set_ == 0)) { // The char server should know what IP address it is running on // - MouseJstr int localaddr = ntohl(addr_[0]); unsigned char *ptr = (unsigned char *) &localaddr; char buf[16]; sprintf(buf, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);; - if (naddr_ != 1) + if (naddr_ != 1) printf("Multiple interfaces detected.. using %s as our IP address\n", buf); else printf("Defaulting to %s as our IP address\n", buf); @@ -3386,9 +3532,9 @@ int do_init(int argc, char **argv) { if (char_ip_set_ == 0) strcpy(char_ip_str, buf); - if (ptr[0] == 192 && ptr[1] == 168) - printf("Firewall detected.. edit lan_support.conf and char_athena.conf"); - } + if (ptr[0] == 192 && ptr[1] == 168) + printf("Firewall detected.. edit lan_support.conf and char_athena.conf\n"); + } login_ip = inet_addr(login_ip_str); char_ip = inet_addr(char_ip_str); @@ -3399,7 +3545,7 @@ int do_init(int argc, char **argv) { } online_players_max = 256; - online_chars = calloc(sizeof(struct online_chars) * 256, 1); + online_chars = (struct online_chars*)aCalloc(sizeof(struct online_chars) * 256, 1); if (!online_chars) { printf("out of memory: do_init (calloc).\n"); exit(1); @@ -3409,7 +3555,6 @@ int do_init(int argc, char **argv) { online_chars[i].server = -1; } - mmo_char_init(); update_online = time(NULL); @@ -3420,12 +3565,15 @@ int do_init(int argc, char **argv) { set_termfunc(do_final); set_defaultparse(parse_char); - char_fd = make_listen_port(char_port); + if (bind_ip_set_) + char_fd = make_listen_bind(inet_addr(bind_ip_str),char_port); + else + char_fd = make_listen_bind(INADDR_ANY,char_port); add_timer_func_list(check_connect_login_server, "check_connect_login_server"); add_timer_func_list(send_users_tologin, "send_users_tologin"); add_timer_func_list(mmo_char_sync_timer, "mmo_char_sync_timer"); - + i = add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000); i = add_timer_interval(gettick() + 1000, send_users_tologin, 0, 0, 5 * 1000); i = add_timer_interval(gettick() + autosave_interval, mmo_char_sync_timer, 0, 0, autosave_interval); @@ -3438,13 +3586,6 @@ int do_init(int argc, char **argv) { if (flush_on) add_timer_interval(gettick()+10, flush_timer,0,0,flush_time); - - - if(anti_freeze_enable > 0) { - add_timer_func_list(map_anti_freeze_system, "map_anti_freeze_system"); - i = add_timer_interval(gettick() + 1000, map_anti_freeze_system, 0, 0, ANTI_FREEZE_INTERVAL * 1000); // checks every X seconds user specifies - } - if(console) { set_defaultconsoleparse(parse_console); start_console(); @@ -3456,3 +3597,19 @@ int do_init(int argc, char **argv) { return 0; } + +int char_married(int pl1,int pl2) { + if (char_dat[pl1].char_id == char_dat[pl2].partner_id && char_dat[pl2].char_id == char_dat[pl1].partner_id) + return 1; + else + return 0; +} + +int char_child(int parent_id, int child_id) { + if (char_dat[parent_id].child == char_dat[child_id].char_id && + ((char_dat[parent_id].char_id == char_dat[child_id].father) || + (char_dat[parent_id].char_id == char_dat[child_id].mother))) + return 1; + else + return 0; +} diff --git a/src/char/char.h b/src/char/char.h index 3ee2f9f6d..78f4f0194 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -24,6 +24,9 @@ int mapif_sendall(unsigned char *buf, unsigned int len); int mapif_sendallwos(int fd,unsigned char *buf, unsigned int len); int mapif_send(int fd,unsigned char *buf, unsigned int len); +int char_married(int pl1,int pl2); +int char_child(int parent_id, int child_id); + int char_log(char *fmt, ...); extern int autosave_interval; diff --git a/src/char/int_guild.c b/src/char/int_guild.c index eb03dd335..9268d9339 100644 --- a/src/char/int_guild.c +++ b/src/char/int_guild.c @@ -45,7 +45,7 @@ int inter_guild_tostr(char *str, struct guild *g) { len += sprintf(str + len, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\t%s\t", m->account_id, m->char_id, m->hair, m->hair_color, m->gender, - m->class, m->lv, m->exp, m->exp_payper, m->position, + m->class_, m->lv, m->exp, m->exp_payper, m->position, ((m->account_id > 0) ? m->name : "-")); } // –ðE @@ -138,7 +138,7 @@ int inter_guild_fromstr(char *str, struct guild *g) { m->hair = tmp_int[2]; m->hair_color = tmp_int[3]; m->gender = tmp_int[4]; - m->class = tmp_int[5]; + m->class_ = tmp_int[5]; m->lv = tmp_int[6]; m->exp = tmp_int[7]; m->exp_payper = tmp_int[8]; @@ -398,7 +398,7 @@ int inter_guild_init() { continue; } - g = calloc(sizeof(struct guild), 1); + g = (struct guild *) aCalloc(sizeof(struct guild), 1); if(g == NULL){ printf("int_guild: out of memory!\n"); exit(0); @@ -412,7 +412,7 @@ int inter_guild_init() { guild_calcinfo(g); } else { printf("int_guild: broken data [%s] line %d\n", guild_txt, c); - free(g); + aFree(g); } c++; } @@ -426,7 +426,7 @@ int inter_guild_init() { } while(fgets(line, sizeof(line)-1, fp)) { - gc = calloc(sizeof(struct guild_castle), 1); + gc = (struct guild_castle *) aCalloc(sizeof(struct guild_castle), 1); if(gc == NULL){ printf("int_guild: out of memory!\n"); exit(0); @@ -436,7 +436,7 @@ int inter_guild_init() { numdb_insert(castle_db, gc->castle_id, gc); } else { printf("int_guild: broken data [%s] line %d\n", castle_txt, c); - free(gc); + aFree(gc); } c++; } @@ -445,7 +445,7 @@ int inter_guild_init() { printf(" %s - making Default Data...\n", castle_txt); //ƒfƒtƒHƒ‹ƒgƒf[ƒ^‚ðì¬ for(i = 0; i < MAX_GUILDCASTLE; i++) { - gc = calloc(sizeof(struct guild_castle), 1); + gc = (struct guild_castle *) aCalloc(sizeof(struct guild_castle), 1); if (gc == NULL) { printf("int_guild: out of memory!\n"); exit(0); @@ -488,10 +488,28 @@ int inter_guild_init() { return 0; } +int castle_db_final (void *k, void *data, va_list ap) +{ + struct guild_castle *gc = (struct guild_castle *) data; + if (gc) aFree(gc); + return 0; +} +int guild_db_final (void *k, void *data, va_list ap) +{ + struct guild *g = (struct guild *) data; + if (g) aFree(g); + return 0; +} +void inter_guild_final() { + numdb_final(castle_db, castle_db_final); + numdb_final(guild_db, guild_db_final); + return; +} + struct guild *inter_guild_search(int guild_id) { struct guild *g; - g=numdb_search(guild_db, guild_id); + g = (struct guild *) numdb_search(guild_db, guild_id); return g; } @@ -577,7 +595,7 @@ int guild_check_empty(struct guild *g) { numdb_erase(guild_db, g->guild_id); inter_guild_storage_delete(g->guild_id); mapif_guild_broken(g->guild_id, 0); - free(g); + aFree(g); return 1; } @@ -656,7 +674,7 @@ int guild_calcinfo(struct guild *g) { g->next_exp = guild_nextexp(g->guild_lv); // ƒƒ“ƒoãŒÀiƒMƒ‹ƒhŠg’£“K—pj - g->max_member = 16 + guild_checkskill(g, GD_EXTENSION) * 2; + g->max_member = 16 + guild_checkskill(g, GD_EXTENSION) * 6; //Lupus 2 -> 6 // •½‹ÏƒŒƒxƒ‹‚ƃIƒ“ƒ‰ƒCƒ“l” g->average_lv = 0; @@ -713,7 +731,7 @@ int mapif_guild_noinfo(int fd, int guild_id) { // ƒMƒ‹ƒhî•ñ‚܂Ƃߑ—‚è int mapif_guild_info(int fd, struct guild *g) { - unsigned char buf[4 + sizeof(struct guild)]; + unsigned char buf[16384]; WBUFW(buf,0) = 0x3831; memcpy(buf + 4, g, sizeof(struct guild)); @@ -765,9 +783,9 @@ int mapif_guild_memberinfoshort(struct guild *g, int idx) { WBUFL(buf, 2) = g->guild_id; WBUFL(buf, 6) = g->member[idx].account_id; WBUFL(buf,10) = g->member[idx].char_id; - WBUFB(buf,14) = g->member[idx].online; + WBUFB(buf,14) = (unsigned char)g->member[idx].online; WBUFW(buf,15) = g->member[idx].lv; - WBUFW(buf,17) = g->member[idx].class; + WBUFW(buf,17) = g->member[idx].class_; mapif_sendall(buf, 19); return 0; } @@ -786,15 +804,15 @@ int mapif_guild_broken(int guild_id, int flag) { } // ƒMƒ‹ƒh“à”Œ¾ -int mapif_guild_message(int guild_id, int account_id, char *mes, int len) { - unsigned char buf[len+12]; +int mapif_guild_message(int guild_id, int account_id, char *mes, int len, int sfd) { + unsigned char buf[2048]; WBUFW(buf,0) = 0x3837; WBUFW(buf,2) = len + 12; WBUFL(buf,4) = guild_id; WBUFL(buf,8) = account_id; memcpy(WBUFP(buf,12), mes, len); - mapif_sendall(buf, len + 12); + mapif_sendallwos(sfd, buf, len + 12); return 0; } @@ -814,7 +832,7 @@ int mapif_guild_basicinfochanged(int guild_id, int type, const void *data, int l // ƒMƒ‹ƒhƒƒ“ƒoî•ñ•ÏX’Ê’m int mapif_guild_memberinfochanged(int guild_id, int account_id, int char_id, int type, const void *data, int len) { - unsigned char buf[len + 18]; + unsigned char buf[4096]; WBUFW(buf, 0) = 0x383a; WBUFW(buf, 2) = len + 18; @@ -860,7 +878,7 @@ int mapif_guild_alliance(int guild_id1, int guild_id2, int account_id1, int acco // ƒMƒ‹ƒh–ðE•ÏX’Ê’m int mapif_guild_position(struct guild *g, int idx) { - unsigned char buf[sizeof(struct guild_position) + 12]; + unsigned char buf[2048]; WBUFW(buf,0) = 0x383b; WBUFW(buf,2) = sizeof(struct guild_position) + 12; @@ -965,7 +983,7 @@ int mapif_parse_CreateGuild(int fd, int account_id, char *name, struct guild_mem mapif_guild_created(fd, account_id, NULL); return 0; } - g = calloc(sizeof(struct guild), 1); + g = (struct guild *) aCalloc(sizeof(struct guild), 1); if (g == NULL) { printf("int_guild: CreateGuild: out of memory !\n"); mapif_guild_created(fd, account_id, NULL); @@ -1005,7 +1023,7 @@ int mapif_parse_CreateGuild(int fd, int account_id, char *name, struct guild_mem int mapif_parse_GuildInfo(int fd, int guild_id) { struct guild *g; - g = numdb_search(guild_db, guild_id); + g = (struct guild *) numdb_search(guild_db, guild_id); if (g != NULL){ guild_calcinfo(g); mapif_guild_info(fd, g); @@ -1020,7 +1038,7 @@ int mapif_parse_GuildAddMember(int fd, int guild_id, struct guild_member *m) { struct guild *g; int i; - g = numdb_search(guild_db, guild_id); + g = (struct guild *) numdb_search(guild_db, guild_id); if (g == NULL) { mapif_guild_memberadded(fd, guild_id, m->account_id, m->char_id, 1); return 0; @@ -1046,7 +1064,7 @@ int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, in struct guild *g = NULL; int i, j; - g = numdb_search(guild_db, guild_id); + g = (struct guild *)numdb_search(guild_db, guild_id); if (g != NULL) { for(i = 0; i < MAX_GUILD; i++) { if (g->member[i].account_id == account_id && g->member[i].char_id == char_id) { @@ -1085,11 +1103,11 @@ int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, in } // ƒIƒ“ƒ‰ƒCƒ“/LvXV -int mapif_parse_GuildChangeMemberInfoShort(int fd, int guild_id, int account_id, int char_id, int online, int lv, int class) { +int mapif_parse_GuildChangeMemberInfoShort(int fd, int guild_id, int account_id, int char_id, int online, int lv, int class_) { struct guild *g; int i, alv, c; - g = numdb_search(guild_db, guild_id); + g = (struct guild *) numdb_search(guild_db, guild_id); if (g == NULL) return 0; @@ -1101,7 +1119,7 @@ int mapif_parse_GuildChangeMemberInfoShort(int fd, int guild_id, int account_id, if (g->member[i].account_id == account_id && g->member[i].char_id == char_id) { g->member[i].online = online; g->member[i].lv = lv; - g->member[i].class = class; + g->member[i].class_ = class_; mapif_guild_memberinfoshort(g, i); } if (g->member[i].account_id > 0) { @@ -1111,8 +1129,10 @@ int mapif_parse_GuildChangeMemberInfoShort(int fd, int guild_id, int account_id, if (g->member[i].online) g->connect_member++; } - // •½‹ÏƒŒƒxƒ‹ - g->average_lv = alv / c; + + if (c) + // •½‹ÏƒŒƒxƒ‹ + g->average_lv = alv / c; return 0; } @@ -1134,7 +1154,7 @@ int guild_break_sub(void *key, void *data, va_list ap) { int mapif_parse_BreakGuild(int fd, int guild_id) { struct guild *g; - g = numdb_search(guild_db, guild_id); + g = (struct guild *) numdb_search(guild_db, guild_id); if(g == NULL) return 0; @@ -1145,14 +1165,14 @@ int mapif_parse_BreakGuild(int fd, int guild_id) { if(log_inter) inter_log("guild %s (id=%d) broken" RETCODE, g->name, guild_id); - free(g); + aFree(g); return 0; } // ƒMƒ‹ƒhƒƒbƒZ[ƒW‘—M int mapif_parse_GuildMessage(int fd, int guild_id, int account_id, char *mes, int len) { - return mapif_guild_message(guild_id, account_id, mes, len); + return mapif_guild_message(guild_id, account_id, mes, len, fd); } // ƒMƒ‹ƒhŠî–{ƒf[ƒ^•ÏX—v‹ @@ -1160,7 +1180,7 @@ int mapif_parse_GuildBasicInfoChange(int fd, int guild_id, int type, const char struct guild *g; short dw = *((short *)data); - g = numdb_search(guild_db, guild_id); + g = (struct guild *) numdb_search(guild_db, guild_id); if (g == NULL) return 0; @@ -1187,7 +1207,7 @@ int mapif_parse_GuildMemberInfoChange(int fd, int guild_id, int account_id, int int i; struct guild *g; - g = numdb_search(guild_db, guild_id); + g = (struct guild *) numdb_search(guild_db, guild_id); if(g == NULL) return 0; @@ -1222,7 +1242,7 @@ int mapif_parse_GuildMemberInfoChange(int fd, int guild_id, int account_id, int // ƒMƒ‹ƒh–ðE–¼•ÏX—v‹ int mapif_parse_GuildPosition(int fd, int guild_id, int idx, struct guild_position *p) { - struct guild *g = numdb_search(guild_db, guild_id); + struct guild *g = (struct guild *) numdb_search(guild_db, guild_id); if (g == NULL || idx < 0 || idx >= MAX_GUILDPOSITION) { return 0; @@ -1236,7 +1256,7 @@ int mapif_parse_GuildPosition(int fd, int guild_id, int idx, struct guild_positi // ƒMƒ‹ƒhƒXƒLƒ‹ƒAƒbƒv—v‹ int mapif_parse_GuildSkillUp(int fd, int guild_id, int skill_num, int account_id) { - struct guild *g = numdb_search(guild_db, guild_id); + struct guild *g = (struct guild *) numdb_search(guild_db, guild_id); int idx = skill_num - GD_SKILLBASE; if (g == NULL || idx < 0 || idx >= MAX_GUILDSKILL) @@ -1259,8 +1279,8 @@ int mapif_parse_GuildAlliance(int fd, int guild_id1, int guild_id2, int account_ struct guild *g[2]; int j, i; - g[0] = numdb_search(guild_db, guild_id1); - g[1] = numdb_search(guild_db, guild_id2); + g[0] = (struct guild *) numdb_search(guild_db, guild_id1); + g[1] = (struct guild *) numdb_search(guild_db, guild_id2); if (g[0] == NULL || g[1] == NULL) return 0; @@ -1292,7 +1312,7 @@ int mapif_parse_GuildAlliance(int fd, int guild_id1, int guild_id2, int account_ int mapif_parse_GuildNotice(int fd, int guild_id, const char *mes1, const char *mes2) { struct guild *g; - g = numdb_search(guild_db, guild_id); + g = (struct guild *) numdb_search(guild_db, guild_id); if (g == NULL) return 0; memcpy(g->mes1, mes1, 60); @@ -1305,7 +1325,7 @@ int mapif_parse_GuildNotice(int fd, int guild_id, const char *mes1, const char * int mapif_parse_GuildEmblem(int fd, int len, int guild_id, int dummy, const char *data) { struct guild *g; - g = numdb_search(guild_db, guild_id); + g = (struct guild *) numdb_search(guild_db, guild_id); if (g == NULL) return 0; memcpy(g->emblem_data, data, len); @@ -1316,7 +1336,7 @@ int mapif_parse_GuildEmblem(int fd, int len, int guild_id, int dummy, const char } int mapif_parse_GuildCastleDataLoad(int fd, int castle_id, int index) { - struct guild_castle *gc = numdb_search(castle_db, castle_id); + struct guild_castle *gc = (struct guild_castle *) numdb_search(castle_db, castle_id); if (gc == NULL) { return mapif_guild_castle_dataload(castle_id, 0, 0); @@ -1357,7 +1377,7 @@ int mapif_parse_GuildCastleDataLoad(int fd, int castle_id, int index) { } int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value) { - struct guild_castle *gc=numdb_search(castle_db, castle_id); + struct guild_castle *gc= (struct guild_castle *) numdb_search(castle_db, castle_id); if (gc == NULL) { return mapif_guild_castle_datasave(castle_id, index, value); @@ -1366,10 +1386,10 @@ int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value) case 1: if (gc->guild_id != value) { int gid = (value) ? value : gc->guild_id; - struct guild *g = numdb_search(guild_db, gid); + struct guild *g = (struct guild *) numdb_search(guild_db, gid); if(log_inter) inter_log("guild %s (id=%d) %s castle id=%d" RETCODE, - (g) ? g->name : "??", gid, (value) ? "occupy" : "abandon", index); + (g) ? g->name : "??", gid, (value) ? "occupy" : "abandon", castle_id); } gc->guild_id = value; break; @@ -1417,21 +1437,21 @@ int mapif_parse_GuildCheck(int fd, int guild_id, int account_id, int char_id) { // EƒGƒ‰[‚È‚ç0(false)A‚»‚¤‚łȂ¢‚È‚ç1(true)‚ð‚©‚¦‚³‚È‚¯‚ê‚΂Ȃç‚È‚¢ int inter_guild_parse_frommap(int fd) { switch(RFIFOW(fd,0)) { - case 0x3030: mapif_parse_CreateGuild(fd, RFIFOL(fd,4), RFIFOP(fd,8), (struct guild_member *)RFIFOP(fd,32)); break; + case 0x3030: mapif_parse_CreateGuild(fd, RFIFOL(fd,4), (char*)RFIFOP(fd,8), (struct guild_member *)RFIFOP(fd,32)); break; case 0x3031: mapif_parse_GuildInfo(fd, RFIFOL(fd,2)); break; case 0x3032: mapif_parse_GuildAddMember(fd, RFIFOL(fd,4), (struct guild_member *)RFIFOP(fd,8)); break; - case 0x3034: mapif_parse_GuildLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOB(fd,14), RFIFOP(fd,15)); break; + case 0x3034: mapif_parse_GuildLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOB(fd,14), (const char*)RFIFOP(fd,15)); break; case 0x3035: mapif_parse_GuildChangeMemberInfoShort(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOB(fd,14), RFIFOW(fd,15), RFIFOW(fd,17)); break; case 0x3036: mapif_parse_BreakGuild(fd, RFIFOL(fd,2)); break; - case 0x3037: mapif_parse_GuildMessage(fd, RFIFOL(fd,4), RFIFOL(fd,8), RFIFOP(fd,12), RFIFOW(fd,2)-12); break; + case 0x3037: mapif_parse_GuildMessage(fd, RFIFOL(fd,4), RFIFOL(fd,8), (char*)RFIFOP(fd,12), RFIFOW(fd,2)-12); break; case 0x3038: mapif_parse_GuildCheck(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break; - case 0x3039: mapif_parse_GuildBasicInfoChange(fd, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOP(fd,10), RFIFOW(fd,2)-10); break; - case 0x303A: mapif_parse_GuildMemberInfoChange(fd, RFIFOL(fd,4), RFIFOL(fd,8), RFIFOL(fd,12), RFIFOW(fd,16), RFIFOP(fd,18), RFIFOW(fd,2)-18); break; + case 0x3039: mapif_parse_GuildBasicInfoChange(fd, RFIFOL(fd,4), RFIFOW(fd,8), (const char*)RFIFOP(fd,10), RFIFOW(fd,2)-10); break; + case 0x303A: mapif_parse_GuildMemberInfoChange(fd, RFIFOL(fd,4), RFIFOL(fd,8), RFIFOL(fd,12), RFIFOW(fd,16), (const char*)RFIFOP(fd,18), RFIFOW(fd,2)-18); break; case 0x303B: mapif_parse_GuildPosition(fd, RFIFOL(fd,4), RFIFOL(fd,8), (struct guild_position *)RFIFOP(fd,12)); break; case 0x303C: mapif_parse_GuildSkillUp(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break; case 0x303D: mapif_parse_GuildAlliance(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOB(fd,18)); break; - case 0x303E: mapif_parse_GuildNotice(fd, RFIFOL(fd,2), RFIFOP(fd,6), RFIFOP(fd,66)); break; - case 0x303F: mapif_parse_GuildEmblem(fd, RFIFOW(fd,2)-12, RFIFOL(fd,4), RFIFOL(fd,8), RFIFOP(fd,12)); break; + case 0x303E: mapif_parse_GuildNotice(fd, RFIFOL(fd,2), (const char*)RFIFOP(fd,6), (const char*)RFIFOP(fd,66)); break; + case 0x303F: mapif_parse_GuildEmblem(fd, RFIFOW(fd,2)-12, RFIFOL(fd,4), RFIFOL(fd,8), (const char*)RFIFOP(fd,12)); break; case 0x3040: mapif_parse_GuildCastleDataLoad(fd, RFIFOW(fd,2), RFIFOB(fd,4)); break; case 0x3041: mapif_parse_GuildCastleDataSave(fd, RFIFOW(fd,2), RFIFOB(fd,4), RFIFOL(fd,5)); break; diff --git a/src/char/int_guild.h b/src/char/int_guild.h index 555f5e123..3eeb1b3db 100644 --- a/src/char/int_guild.h +++ b/src/char/int_guild.h @@ -3,6 +3,7 @@ #define _INT_GUILD_H_ int inter_guild_init(); +void inter_guild_final(); int inter_guild_save(); int inter_guild_parse_frommap(int fd); struct guild *inter_guild_search(int guild_id); diff --git a/src/char/int_party.c b/src/char/int_party.c index 0fd58fa14..299a75135 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -19,7 +19,7 @@ int mapif_party_broken(int party_id, int flag); int party_check_empty(struct party *p); int mapif_parse_PartyLeave(int fd, int party_id, int account_id); -// ƒp[ƒeƒBƒf[ƒ^‚Ì•¶Žš—ñ‚ւ̕ϊ· +// ƒp?ƒeƒBƒf?ƒ^‚Ì•¶Žš—ñ‚Ö‚Ì?Š· int inter_party_tostr(char *str, struct party *p) { int i, len; @@ -32,7 +32,7 @@ int inter_party_tostr(char *str, struct party *p) { return 0; } -// ƒp[ƒeƒBƒf[ƒ^‚Ì•¶Žš—ñ‚©‚ç‚̕ϊ· +// ƒp?ƒeƒBƒf?ƒ^‚Ì•¶Žš—ñ‚©‚ç‚Ì?Š· int inter_party_fromstr(char *str, struct party *p) { int i, j; int tmp_int[16]; @@ -74,7 +74,7 @@ int inter_party_fromstr(char *str, struct party *p) { return 0; } -// ƒp[ƒeƒBƒf[ƒ^‚̃[ƒh +// ƒp?ƒeƒBƒf?ƒ^‚̃?ƒh int inter_party_init() { char line[8192]; struct party *p; @@ -94,7 +94,7 @@ int inter_party_init() { continue; } - p = calloc(sizeof(struct party), 1); + p = (struct party*)aCalloc(sizeof(struct party), 1); if (p == NULL){ printf("int_party: out of memory!\n"); exit(0); @@ -107,7 +107,7 @@ int inter_party_init() { party_check_empty(p); } else { printf("int_party: broken data [%s] line %d\n", party_txt, c + 1); - free(p); + aFree(p); } c++; } @@ -117,7 +117,18 @@ int inter_party_init() { return 0; } -// ƒp[ƒeƒB[ƒf[ƒ^‚̃Z[ƒu—p +int party_db_final (void *k, void *data, va_list ap) { + struct party *p = (struct party *) data; + if (p) aFree(p); + return 0; +} +void inter_party_final() +{ + numdb_final(party_db, party_db_final); + return; +} + +// ƒp?ƒeƒB?ƒf?ƒ^‚̃Z?ƒu—p int inter_party_save_sub(void *key, void *data, va_list ap) { char line[8192]; FILE *fp; @@ -129,7 +140,7 @@ int inter_party_save_sub(void *key, void *data, va_list ap) { return 0; } -// ƒp[ƒeƒB[ƒf[ƒ^‚̃Z[ƒu +// ƒp?ƒeƒB?ƒf?ƒ^‚̃Z?ƒu int inter_party_save() { FILE *fp; int lock; @@ -146,7 +157,7 @@ int inter_party_save() { return 0; } -// ƒp[ƒeƒB–¼ŒŸõ—p +// ƒp?ƒeƒB–¼?õ—p int search_partyname_sub(void *key,void *data,va_list ap) { struct party *p = (struct party *)data,**dst; char *str; @@ -159,7 +170,7 @@ int search_partyname_sub(void *key,void *data,va_list ap) { return 0; } -// ƒp[ƒeƒB–¼ŒŸõ +// ƒp?ƒeƒB–¼?õ struct party* search_partyname(char *str) { struct party *p = NULL; numdb_foreach(party_db, search_partyname_sub, str, &p); @@ -169,7 +180,8 @@ struct party* search_partyname(char *str) { // EXPŒö•½•ª”z‚Å‚«‚é‚©ƒ`ƒFƒbƒN int party_check_exp_share(struct party *p) { - int i; + int i, dudes=0; + int pl1=0,pl2=0,pl3=0; int maxlv = 0, minlv = 0x7fffffff; for(i = 0; i < MAX_PARTY; i++) { @@ -179,13 +191,26 @@ int party_check_exp_share(struct party *p) { minlv = lv; if (maxlv < lv) maxlv = lv; + if( lv >= 70 ) dudes+=1000; + dudes++; } } - - return (maxlv == 0 || maxlv-minlv <= party_share_level); + if((dudes/1000 >= 2) && (dudes%1000 == 3) && (!strcmp(p->member[0].map,p->member[1].map)) && (!strcmp(p->member[1].map,p->member[2].map))) { + pl1=search_character_index(p->member[0].name); + pl2=search_character_index(p->member[1].name); + pl3=search_character_index(p->member[2].name); + printf("PARTY: group of 3 Id1 %d lv %d name %s Id2 %d lv %d name %s Id3 %d lv %d name %s\n",pl1,p->member[0].lv,p->member[0].name,pl2,p->member[1].lv,p->member[1].name,pl3,p->member[2].lv,p->member[2].name); + if (char_married(pl1,pl2) && char_child(pl1,pl3)) + return 1; + if (char_married(pl1,pl3) && char_child(pl1,pl2)) + return 1; + if (char_married(pl2,pl3) && char_child(pl2,pl1)) + return 1; + } + return (maxlv==0 || maxlv-minlv<=party_share_level); } -// ƒp[ƒeƒB‚ª‹ó‚©‚Ç‚¤‚©ƒ`ƒFƒbƒN +// ƒp?ƒeƒB‚ª‹ó‚©‚Ç‚¤‚©ƒ`ƒFƒbƒN int party_check_empty(struct party *p) { int i; @@ -199,7 +224,7 @@ int party_check_empty(struct party *p) { // ’N‚à‚¢‚È‚¢‚̂ʼnðŽU mapif_party_broken(p->party_id, 0); numdb_erase(party_db, p->party_id); - free(p); + aFree(p); return 1; } @@ -214,12 +239,12 @@ int party_check_conflict_sub(void *key, void *data, va_list ap) { account_id=va_arg(ap, int); nick=va_arg(ap, char *); - if (p->party_id == party_id) // –{—ˆ‚ÌŠ‘®‚Ȃ̂Ŗâ‘è‚È‚µ + if (p->party_id == party_id) // –{?‚ÌŠ?‚Ȃ̂Ŗâ‘è‚È‚µ return 0; for(i = 0; i < MAX_PARTY; i++) { if (p->member[i].account_id == account_id && strcmp(p->member[i].name, nick) == 0) { - // •ʂ̃p[ƒeƒB‚É‹U‚ÌŠ‘®ƒf[ƒ^‚ª‚ ‚é‚̂ŒE‘Þ + // •ʂ̃p?ƒeƒB‚É?‚ÌŠ?ƒf?ƒ^‚ª‚ ‚é‚Ì‚Å?‘Þ printf("int_party: party conflict! %d %d %d\n", account_id, party_id, p->party_id); mapif_parse_PartyLeave(-1, p->party_id, account_id); } @@ -238,7 +263,7 @@ int party_check_conflict(int party_id, int account_id, char *nick) { //------------------------------------------------------------------- // map server‚Ö‚Ì’ÊM -// ƒp[ƒeƒBì¬‰Â”Û +// ƒp?ƒeƒBì¬‰Â”Û int mapif_party_created(int fd,int account_id, struct party *p) { WFIFOW(fd,0) = 0x3820; WFIFOL(fd,2) = account_id; @@ -257,7 +282,7 @@ int mapif_party_created(int fd,int account_id, struct party *p) { return 0; } -// ƒp[ƒeƒBî•ñŒ©‚‚©‚炸 +// ƒp?ƒeƒBî•ñŒ©‚‚©‚炸 int mapif_party_noinfo(int fd, int party_id) { WFIFOW(fd,0) = 0x3821; WFIFOW(fd,2) = 8; @@ -268,9 +293,9 @@ int mapif_party_noinfo(int fd, int party_id) { return 0; } -// ƒp[ƒeƒBî•ñ‚܂Ƃߑ—‚è +// ƒp?ƒeƒBî•ñ‚܂Ƃߑ—‚è int mapif_party_info(int fd, struct party *p) { - unsigned char buf[4 + sizeof(struct party)]; + unsigned char buf[2048]; WBUFW(buf,0) = 0x3821; memcpy(buf + 4, p, sizeof(struct party)); @@ -284,7 +309,7 @@ int mapif_party_info(int fd, struct party *p) { return 0; } -// ƒp[ƒeƒBƒƒ“ƒo’ljÁ‰Â”Û +// ƒp?ƒeƒBƒƒ“ƒo’ljÁ‰Â”Û int mapif_party_memberadded(int fd, int party_id, int account_id, int flag) { WFIFOW(fd,0) = 0x3822; WFIFOL(fd,2) = party_id; @@ -295,7 +320,7 @@ int mapif_party_memberadded(int fd, int party_id, int account_id, int flag) { return 0; } -// ƒp[ƒeƒBÝ’è•ÏX’Ê’m +// ƒp?ƒeƒBÝ’è?X’Ê’m int mapif_party_optionchanged(int fd,struct party *p, int account_id, int flag) { unsigned char buf[15]; @@ -314,7 +339,7 @@ int mapif_party_optionchanged(int fd,struct party *p, int account_id, int flag) return 0; } -// ƒp[ƒeƒB’E‘Þ’Ê’m +// ƒp?ƒeƒB?‘Þ’Ê’m int mapif_party_leaved(int party_id,int account_id, char *name) { unsigned char buf[34]; @@ -328,7 +353,7 @@ int mapif_party_leaved(int party_id,int account_id, char *name) { return 0; } -// ƒp[ƒeƒBƒ}ƒbƒvXV’Ê’m +// ƒp?ƒeƒBƒ}ƒbƒvXV’Ê’m int mapif_party_membermoved(struct party *p, int idx) { unsigned char buf[29]; @@ -343,7 +368,7 @@ int mapif_party_membermoved(struct party *p, int idx) { return 0; } -// ƒp[ƒeƒB‰ðŽU’Ê’m +// ƒp?ƒeƒB‰ðŽU’Ê’m int mapif_party_broken(int party_id, int flag) { unsigned char buf[7]; WBUFW(buf,0) = 0x3826; @@ -355,16 +380,16 @@ int mapif_party_broken(int party_id, int flag) { return 0; } -// ƒp[ƒeƒB“à”Œ¾ -int mapif_party_message(int party_id, int account_id, char *mes, int len) { - unsigned char buf[len+12]; +// ƒp?ƒeƒB??Œ¾ +int mapif_party_message(int party_id, int account_id, char *mes, int len, int sfd) { + unsigned char buf[2048]; WBUFW(buf,0) = 0x3827; WBUFW(buf,2) = len + 12; WBUFL(buf,4) = party_id; WBUFL(buf,8) = account_id; memcpy(WBUFP(buf,12), mes, len); - mapif_sendall(buf,len + 12); + mapif_sendallwos(sfd, buf,len + 12); return 0; } @@ -373,8 +398,8 @@ int mapif_party_message(int party_id, int account_id, char *mes, int len) { // map server‚©‚ç‚Ì’ÊM -// ƒp[ƒeƒB -int mapif_parse_CreateParty(int fd, int account_id, char *name, char *nick, char *map, int lv) { +// ƒp?ƒeƒB +int mapif_parse_CreateParty(int fd, int account_id, char *name, char *nick, char *map, int lv, int item, int item2) { struct party *p; int i; @@ -391,7 +416,7 @@ int mapif_parse_CreateParty(int fd, int account_id, char *name, char *nick, char mapif_party_created(fd, account_id, NULL); return 0; } - p = calloc(sizeof(struct party), 1); + p = (struct party *) aCalloc(sizeof(struct party), 1); if (p == NULL) { printf("int_party: out of memory !\n"); mapif_party_created(fd,account_id,NULL); @@ -401,7 +426,12 @@ int mapif_parse_CreateParty(int fd, int account_id, char *name, char *nick, char p->party_id = party_newid++; memcpy(p->name, name, 24); p->exp = 0; - p->item = 0; + p->item = item; + //<item1>ƒAƒCƒeƒ€?W•û–@B0‚ÅŒÂl•ÊA1‚Ńp?ƒeƒBŒö—L + //<item2>ƒAƒCƒeƒ€•ª”z•û–@B0‚ÅŒÂl•ÊA1‚Ńp?ƒeƒB‚ɋϓ™•ª”z + //difference between "collection" and "distribution" is...? ^^; + p->itemc = 0; + p->member[0].account_id = account_id; memcpy(p->member[0].name, nick, 24); memcpy(p->member[0].map, map, 16); @@ -417,11 +447,11 @@ int mapif_parse_CreateParty(int fd, int account_id, char *name, char *nick, char return 0; } -// ƒp[ƒeƒBî•ñ—v‹ +// ƒp?ƒeƒBî•ñ—v‹ int mapif_parse_PartyInfo(int fd, int party_id) { struct party *p; - p = numdb_search(party_db, party_id); + p = (struct party *) numdb_search(party_db, party_id); if (p != NULL) mapif_party_info(fd, p); else @@ -430,12 +460,12 @@ int mapif_parse_PartyInfo(int fd, int party_id) { return 0; } -// ƒp[ƒeƒB’ljÁ—v‹ +// ƒp?ƒeƒB’ljÁ—v‹ int mapif_parse_PartyAddMember(int fd, int party_id, int account_id, char *nick, char *map, int lv) { struct party *p; int i; - p = numdb_search(party_db, party_id); + p = (struct party *) numdb_search(party_db, party_id); if (p == NULL) { mapif_party_memberadded(fd, party_id, account_id, 1); return 0; @@ -468,12 +498,12 @@ int mapif_parse_PartyAddMember(int fd, int party_id, int account_id, char *nick, return 0; } -// ƒp[ƒeƒB[Ý’è•ÏX—v‹ +// ƒp?ƒeƒB?Ý’è?X—v‹ int mapif_parse_PartyChangeOption(int fd, int party_id, int account_id, int exp, int item) { struct party *p; int flag = 0; - p = numdb_search(party_db, party_id); + p = (struct party *) numdb_search(party_db, party_id); if (p == NULL) return 0; @@ -489,12 +519,12 @@ int mapif_parse_PartyChangeOption(int fd, int party_id, int account_id, int exp, return 0; } -// ƒp[ƒeƒB’E‘Þ—v‹ +// ƒp?ƒeƒB?‘Þ—v‹ int mapif_parse_PartyLeave(int fd, int party_id, int account_id) { struct party *p; int i; - p = numdb_search(party_db, party_id); + p = (struct party *) numdb_search(party_db, party_id); if (p != NULL) { for(i = 0; i < MAX_PARTY; i++) { if (p->member[i].account_id == account_id) { @@ -502,7 +532,7 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id) { memset(&p->member[i], 0, sizeof(struct party_member)); if (party_check_empty(p) == 0) - mapif_party_info(-1, p);// ‚Ü‚¾l‚ª‚¢‚é‚̂Ńf[ƒ^‘—M + mapif_party_info(-1, p);// ‚Ü‚¾l‚ª‚¢‚é‚̂Ńf?ƒ^‘—M return 0; } } @@ -511,12 +541,12 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id) { return 0; } -// ƒp[ƒeƒBƒ}ƒbƒvXV—v‹ +// ƒp?ƒeƒBƒ}ƒbƒvXV—v‹ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, char *map, int online, int lv) { struct party *p; int i; - p = numdb_search(party_db, party_id); + p = (struct party *) numdb_search(party_db, party_id); if (p == NULL) return 0; @@ -542,11 +572,11 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, char *map, return 0; } -// ƒp[ƒeƒB‰ðŽU—v‹ +// ƒp?ƒeƒB‰ðŽU—v‹ int mapif_parse_BreakParty(int fd, int party_id) { struct party *p; - p = numdb_search(party_db, party_id); + p = (struct party *) numdb_search(party_db, party_id); if (p == NULL) return 0; @@ -556,31 +586,31 @@ int mapif_parse_BreakParty(int fd, int party_id) { return 0; } -// ƒp[ƒeƒBƒƒbƒZ[ƒW‘—M +// ƒp?ƒeƒBƒƒbƒZ?ƒW‘—M int mapif_parse_PartyMessage(int fd, int party_id, int account_id, char *mes, int len) { - return mapif_party_message(party_id, account_id, mes, len); + return mapif_party_message(party_id, account_id, mes, len, fd); } -// ƒp[ƒeƒBƒ`ƒFƒbƒN—v‹ +// ƒp?ƒeƒBƒ`ƒFƒbƒN—v‹ int mapif_parse_PartyCheck(int fd, int party_id, int account_id, char *nick) { return party_check_conflict(party_id, account_id, nick); } // map server ‚©‚ç‚Ì’ÊM -// E‚PƒpƒPƒbƒg‚̂݉ðÍ‚·‚邱‚Æ -// EƒpƒPƒbƒg’·ƒf[ƒ^‚Íinter.c‚ɃZƒbƒg‚µ‚Ä‚¨‚‚±‚Æ -// EƒpƒPƒbƒg’·ƒ`ƒFƒbƒN‚âARFIFOSKIP‚͌ĂÑo‚µŒ³‚Ås‚í‚ê‚é‚Ì‚Ås‚Á‚Ă͂Ȃç‚È‚¢ -// EƒGƒ‰[‚È‚ç0(false)A‚»‚¤‚łȂ¢‚È‚ç1(true)‚ð‚©‚¦‚³‚È‚¯‚ê‚΂Ȃç‚È‚¢ +// ?‚PƒpƒPƒbƒg‚̂݉ðÍ‚·‚邱‚Æ +// ?ƒpƒPƒbƒg’·ƒf?ƒ^‚Íinter.c‚ɃZƒbƒg‚µ‚Ä‚¨‚‚±‚Æ +// ?ƒpƒPƒbƒg’·ƒ`ƒFƒbƒN‚âARFIFOSKIP‚͌ĂÑo‚µŒ³‚Ås‚í‚ê‚é‚Ì‚Ås‚Á‚Ă͂Ȃç‚È‚¢ +// ?ƒGƒ‰?‚È‚ç0(false)A‚»‚¤‚łȂ¢‚È‚ç1(true)‚ð‚©‚¦‚³‚È‚¯‚ê‚΂Ȃç‚È‚¢ int inter_party_parse_frommap(int fd) { switch(RFIFOW(fd,0)) { - case 0x3020: mapif_parse_CreateParty(fd, RFIFOL(fd,2), RFIFOP(fd,6), RFIFOP(fd,30), RFIFOP(fd,54), RFIFOW(fd,70)); break; + case 0x3020: mapif_parse_CreateParty(fd, RFIFOL(fd,2), (char*)RFIFOP(fd,6), (char*)RFIFOP(fd,30), (char*)RFIFOP(fd,54), RFIFOW(fd,70), RFIFOB(fd,72), RFIFOB(fd,73)); break; case 0x3021: mapif_parse_PartyInfo(fd, RFIFOL(fd,2)); break; - case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOP(fd,10), RFIFOP(fd,34), RFIFOW(fd,50)); break; + case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,2), RFIFOL(fd,6), (char*)RFIFOP(fd,10), (char*)RFIFOP(fd,34), RFIFOW(fd,50)); break; case 0x3023: mapif_parse_PartyChangeOption(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOW(fd,10), RFIFOW(fd,12)); break; case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6)); break; - case 0x3025: mapif_parse_PartyChangeMap(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOP(fd,10), RFIFOB(fd,26), RFIFOW(fd,27)); break; + case 0x3025: mapif_parse_PartyChangeMap(fd, RFIFOL(fd,2), RFIFOL(fd,6), (char*)RFIFOP(fd,10), RFIFOB(fd,26), RFIFOW(fd,27)); break; case 0x3026: mapif_parse_BreakParty(fd, RFIFOL(fd,2)); break; - case 0x3027: mapif_parse_PartyMessage(fd, RFIFOL(fd,4), RFIFOL(fd,8), RFIFOP(fd,12), RFIFOW(fd,2)-12); break; - case 0x3028: mapif_parse_PartyCheck(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOP(fd,10)); break; + case 0x3027: mapif_parse_PartyMessage(fd, RFIFOL(fd,4), RFIFOL(fd,8), (char*)RFIFOP(fd,12), RFIFOW(fd,2)-12); break; + case 0x3028: mapif_parse_PartyCheck(fd, RFIFOL(fd,2), RFIFOL(fd,6), (char*)RFIFOP(fd,10)); break; default: return 0; } @@ -588,7 +618,7 @@ int inter_party_parse_frommap(int fd) { return 1; } -// ƒT[ƒo[‚©‚ç’E‘Þ—v‹iƒLƒƒƒ‰íœ—pj +// ƒT?ƒo?‚©‚ç?‘Þ—v‹iƒLƒƒƒ‰íœ—pj int inter_party_leave(int party_id, int account_id) { return mapif_parse_PartyLeave(-1, party_id, account_id); } diff --git a/src/char/int_party.h b/src/char/int_party.h index b265b4c2e..e3180f3b7 100644 --- a/src/char/int_party.h +++ b/src/char/int_party.h @@ -3,6 +3,7 @@ #define _INT_PARTY_H_ int inter_party_init(); +void inter_party_final(); int inter_party_save(); int inter_party_parse_frommap(int fd); diff --git a/src/char/int_pet.c b/src/char/int_pet.c index cff1e434f..ab53d0533 100644 --- a/src/char/int_pet.c +++ b/src/char/int_pet.c @@ -30,7 +30,7 @@ int inter_pet_tostr(char *str,struct s_pet *p) p->intimate = 1000; len=sprintf(str,"%d,%d,%s\t%d,%d,%d,%d,%d,%d,%d,%d,%d", - p->pet_id,p->class,p->name,p->account_id,p->char_id,p->level,p->egg_id, + p->pet_id,p->class_,p->name,p->account_id,p->char_id,p->level,p->egg_id, p->equip,p->intimate,p->hungry,p->rename_flag,p->incuvate); return 0; @@ -41,18 +41,18 @@ int inter_pet_fromstr(char *str,struct s_pet *p) int s; int tmp_int[16]; char tmp_str[256]; - + memset(p,0,sizeof(struct s_pet)); - + // printf("sscanf pet main info\n"); s=sscanf(str,"%d,%d,%[^\t]\t%d,%d,%d,%d,%d,%d,%d,%d,%d",&tmp_int[0],&tmp_int[1],tmp_str,&tmp_int[2], &tmp_int[3],&tmp_int[4],&tmp_int[5],&tmp_int[6],&tmp_int[7],&tmp_int[8],&tmp_int[9],&tmp_int[10]); if(s!=12) return 1; - + p->pet_id = tmp_int[0]; - p->class = tmp_int[1]; + p->class_ = tmp_int[1]; memcpy(p->name,tmp_str,24); p->account_id = tmp_int[2]; p->char_id = tmp_int[3]; @@ -88,7 +88,7 @@ int inter_pet_init() if( (fp=fopen(pet_txt,"r"))==NULL ) return 1; while(fgets(line,sizeof(line),fp)){ - p=calloc(sizeof(struct s_pet), 1); + p = (struct s_pet*)aCalloc(sizeof(struct s_pet), 1); if(p==NULL){ printf("int_pet: out of memory!\n"); exit(0); @@ -100,7 +100,7 @@ int inter_pet_init() numdb_insert(pet_db,p->pet_id,p); }else{ printf("int_pet: broken data [%s] line %d\n",pet_txt,c); - free(p); + aFree(p); } c++; } @@ -109,6 +109,17 @@ int inter_pet_init() return 0; } +int pet_db_final (void *k, void *data, va_list ap) { + struct s_pet *p = (struct s_pet *) data; + if (p) aFree(p); + return 0; +} +void inter_pet_final() +{ + numdb_final(pet_db, pet_db_final); + return; +} + int inter_pet_save_sub(void *key,void *data,va_list ap) { char line[8192]; @@ -136,7 +147,7 @@ int inter_pet_save() int inter_pet_delete(int pet_id) { struct s_pet *p; - p = numdb_search(pet_db,pet_id); + p = (struct s_pet *) numdb_search(pet_db,pet_id); if( p == NULL) return 1; else { @@ -210,7 +221,7 @@ int mapif_create_pet(int fd,int account_id,int char_id,short pet_class,short pet short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name) { struct s_pet *p; - p=malloc(sizeof(struct s_pet)); + p= (struct s_pet *) aMalloc(sizeof(struct s_pet)); if(p==NULL){ printf("int_pet: out of memory !\n"); mapif_pet_created(fd,account_id,NULL); @@ -225,7 +236,7 @@ int mapif_create_pet(int fd,int account_id,int char_id,short pet_class,short pet p->account_id = account_id; p->char_id = char_id; } - p->class = pet_class; + p->class_ = pet_class; p->level = pet_lv; p->egg_id = pet_egg_id; p->equip = pet_equip; @@ -242,18 +253,18 @@ int mapif_create_pet(int fd,int account_id,int char_id,short pet_class,short pet p->intimate = 0; else if(p->intimate > 1000) p->intimate = 1000; - + numdb_insert(pet_db,p->pet_id,p); - + mapif_pet_created(fd,account_id,p); - + return 0; } int mapif_load_pet(int fd,int account_id,int char_id,int pet_id) { struct s_pet *p; - p=numdb_search(pet_db,pet_id); + p=(struct s_pet *)numdb_search(pet_db,pet_id); if(p!=NULL) { if(p->incuvate == 1) { p->account_id = p->char_id = 0; @@ -280,9 +291,9 @@ int mapif_save_pet(int fd,int account_id,struct s_pet *data) } else{ pet_id = data->pet_id; - p=numdb_search(pet_db,pet_id); + p=(struct s_pet *)numdb_search(pet_db,pet_id); if(p == NULL) { - p=malloc(sizeof(struct s_pet)); + p=(struct s_pet *)aMalloc(sizeof(struct s_pet)); if(p==NULL){ printf("int_pet: out of memory !\n"); mapif_save_pet_ack(fd,account_id,1); @@ -292,7 +303,7 @@ int mapif_save_pet(int fd,int account_id,struct s_pet *data) p->pet_id = data->pet_id; if(p->pet_id == 0) data->pet_id = p->pet_id = pet_newid++; - numdb_insert(pet_db,p->pet_id,p); + numdb_insert(pet_db,p->pet_id,p); } if(data->hungry < 0) data->hungry = 0; @@ -322,7 +333,7 @@ int mapif_delete_pet(int fd,int pet_id) int mapif_parse_CreatePet(int fd) { mapif_create_pet(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOW(fd,10),RFIFOW(fd,12),RFIFOW(fd,14),RFIFOW(fd,16),RFIFOL(fd,18), - RFIFOL(fd,20),RFIFOB(fd,22),RFIFOB(fd,23),RFIFOP(fd,24)); + RFIFOL(fd,20),RFIFOB(fd,22),RFIFOB(fd,23),(char*)RFIFOP(fd,24)); return 0; } diff --git a/src/char/int_pet.h b/src/char/int_pet.h index 993f913ab..3a48ada3b 100644 --- a/src/char/int_pet.h +++ b/src/char/int_pet.h @@ -3,6 +3,7 @@ #define _INT_PET_H_ int inter_pet_init(); +void inter_pet_final(); int inter_pet_save(); int inter_pet_delete(int pet_id); diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 7a4022a55..eaf9e001a 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -28,11 +28,11 @@ int storage_tostr(char *str,struct storage *p) str_p += sprintf(str_p,"%d,%d\t",p->account_id,p->storage_amount); for(i=0;i<MAX_STORAGE;i++) - if( (p->storage[i].nameid) && (p->storage[i].amount) ){ + if( (p->storage_[i].nameid) && (p->storage_[i].amount) ){ str_p += sprintf(str_p,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ", - p->storage[i].id,p->storage[i].nameid,p->storage[i].amount,p->storage[i].equip, - p->storage[i].identify,p->storage[i].refine,p->storage[i].attribute, - p->storage[i].card[0],p->storage[i].card[1],p->storage[i].card[2],p->storage[i].card[3]); + p->storage_[i].id,p->storage_[i].nameid,p->storage_[i].amount,p->storage_[i].equip, + p->storage_[i].identify,p->storage_[i].refine,p->storage_[i].attribute, + p->storage_[i].card[0],p->storage_[i].card[1],p->storage_[i].card[2],p->storage_[i].card[3]); f++; } @@ -56,49 +56,49 @@ int storage_fromstr(char *str,struct storage *p) if(set!=2) return 1; if(str[next]=='\n' || str[next]=='\r') - return 0; + return 0; next++; for(i=0;str[next] && str[next]!='\t';i++){ if(sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10], &tmp_int[10], &len) == 12) { - p->storage[i].id = tmp_int[0]; - p->storage[i].nameid = tmp_int[1]; - p->storage[i].amount = tmp_int[2]; - p->storage[i].equip = tmp_int[3]; - p->storage[i].identify = tmp_int[4]; - p->storage[i].refine = tmp_int[5]; - p->storage[i].attribute = tmp_int[6]; - p->storage[i].card[0] = tmp_int[7]; - p->storage[i].card[1] = tmp_int[8]; - p->storage[i].card[2] = tmp_int[9]; - p->storage[i].card[3] = tmp_int[10]; + p->storage_[i].id = tmp_int[0]; + p->storage_[i].nameid = tmp_int[1]; + p->storage_[i].amount = tmp_int[2]; + p->storage_[i].equip = tmp_int[3]; + p->storage_[i].identify = tmp_int[4]; + p->storage_[i].refine = tmp_int[5]; + p->storage_[i].attribute = tmp_int[6]; + p->storage_[i].card[0] = tmp_int[7]; + p->storage_[i].card[1] = tmp_int[8]; + p->storage_[i].card[2] = tmp_int[9]; + p->storage_[i].card[3] = tmp_int[10]; next += len; if (str[next] == ' ') - next++; + next++; } else if(sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10], &len) == 11) { - p->storage[i].id = tmp_int[0]; - p->storage[i].nameid = tmp_int[1]; - p->storage[i].amount = tmp_int[2]; - p->storage[i].equip = tmp_int[3]; - p->storage[i].identify = tmp_int[4]; - p->storage[i].refine = tmp_int[5]; - p->storage[i].attribute = tmp_int[6]; - p->storage[i].card[0] = tmp_int[7]; - p->storage[i].card[1] = tmp_int[8]; - p->storage[i].card[2] = tmp_int[9]; - p->storage[i].card[3] = tmp_int[10]; + p->storage_[i].id = tmp_int[0]; + p->storage_[i].nameid = tmp_int[1]; + p->storage_[i].amount = tmp_int[2]; + p->storage_[i].equip = tmp_int[3]; + p->storage_[i].identify = tmp_int[4]; + p->storage_[i].refine = tmp_int[5]; + p->storage_[i].attribute = tmp_int[6]; + p->storage_[i].card[0] = tmp_int[7]; + p->storage_[i].card[1] = tmp_int[8]; + p->storage_[i].card[2] = tmp_int[9]; + p->storage_[i].card[3] = tmp_int[10]; next += len; if (str[next] == ' ') - next++; + next++; } - + else return 1; } return 0; @@ -111,11 +111,11 @@ int guild_storage_tostr(char *str,struct guild_storage *p) str_p+=sprintf(str,"%d,%d\t",p->guild_id,p->storage_amount); for(i=0;i<MAX_GUILD_STORAGE;i++) - if( (p->storage[i].nameid) && (p->storage[i].amount) ){ + if( (p->storage_[i].nameid) && (p->storage_[i].amount) ){ str_p += sprintf(str_p,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ", - p->storage[i].id,p->storage[i].nameid,p->storage[i].amount,p->storage[i].equip, - p->storage[i].identify,p->storage[i].refine,p->storage[i].attribute, - p->storage[i].card[0],p->storage[i].card[1],p->storage[i].card[2],p->storage[i].card[3]); + p->storage_[i].id,p->storage_[i].nameid,p->storage_[i].amount,p->storage_[i].equip, + p->storage_[i].identify,p->storage_[i].refine,p->storage_[i].attribute, + p->storage_[i].card[0],p->storage_[i].card[1],p->storage_[i].card[2],p->storage_[i].card[3]); f++; } @@ -138,49 +138,49 @@ int guild_storage_fromstr(char *str,struct guild_storage *p) if(set!=2) return 1; if(str[next]=='\n' || str[next]=='\r') - return 0; + return 0; next++; for(i=0;str[next] && str[next]!='\t';i++){ if(sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10], &tmp_int[10], &len) == 12) { - p->storage[i].id = tmp_int[0]; - p->storage[i].nameid = tmp_int[1]; - p->storage[i].amount = tmp_int[2]; - p->storage[i].equip = tmp_int[3]; - p->storage[i].identify = tmp_int[4]; - p->storage[i].refine = tmp_int[5]; - p->storage[i].attribute = tmp_int[6]; - p->storage[i].card[0] = tmp_int[7]; - p->storage[i].card[1] = tmp_int[8]; - p->storage[i].card[2] = tmp_int[9]; - p->storage[i].card[3] = tmp_int[10]; + p->storage_[i].id = tmp_int[0]; + p->storage_[i].nameid = tmp_int[1]; + p->storage_[i].amount = tmp_int[2]; + p->storage_[i].equip = tmp_int[3]; + p->storage_[i].identify = tmp_int[4]; + p->storage_[i].refine = tmp_int[5]; + p->storage_[i].attribute = tmp_int[6]; + p->storage_[i].card[0] = tmp_int[7]; + p->storage_[i].card[1] = tmp_int[8]; + p->storage_[i].card[2] = tmp_int[9]; + p->storage_[i].card[3] = tmp_int[10]; next += len; if (str[next] == ' ') - next++; + next++; } else if(sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10], &len) == 11) { - p->storage[i].id = tmp_int[0]; - p->storage[i].nameid = tmp_int[1]; - p->storage[i].amount = tmp_int[2]; - p->storage[i].equip = tmp_int[3]; - p->storage[i].identify = tmp_int[4]; - p->storage[i].refine = tmp_int[5]; - p->storage[i].attribute = tmp_int[6]; - p->storage[i].card[0] = tmp_int[7]; - p->storage[i].card[1] = tmp_int[8]; - p->storage[i].card[2] = tmp_int[9]; - p->storage[i].card[3] = tmp_int[10]; + p->storage_[i].id = tmp_int[0]; + p->storage_[i].nameid = tmp_int[1]; + p->storage_[i].amount = tmp_int[2]; + p->storage_[i].equip = tmp_int[3]; + p->storage_[i].identify = tmp_int[4]; + p->storage_[i].refine = tmp_int[5]; + p->storage_[i].attribute = tmp_int[6]; + p->storage_[i].card[0] = tmp_int[7]; + p->storage_[i].card[1] = tmp_int[8]; + p->storage_[i].card[2] = tmp_int[9]; + p->storage_[i].card[3] = tmp_int[10]; next += len; if (str[next] == ' ') - next++; + next++; } - + else return 1; } return 0; @@ -190,9 +190,9 @@ int guild_storage_fromstr(char *str,struct guild_storage *p) struct storage *account2storage(int account_id) { struct storage *s; - s=numdb_search(storage_db,account_id); + s= (struct storage *) numdb_search(storage_db,account_id); if(s == NULL) { - s = calloc(sizeof(struct storage), 1); + s = (struct storage *) aCalloc(sizeof(struct storage), 1); if(s==NULL){ printf("int_storage: out of memory!\n"); exit(0); @@ -208,9 +208,9 @@ struct guild_storage *guild2storage(int guild_id) { struct guild_storage *gs = NULL; if(inter_guild_search(guild_id) != NULL) { - gs=numdb_search(guild_storage_db,guild_id); + gs= (struct guild_storage *) numdb_search(guild_storage_db,guild_id); if(gs == NULL) { - gs = calloc(sizeof(struct guild_storage), 1); + gs = (struct guild_storage *) aCalloc(sizeof(struct guild_storage), 1); if(gs==NULL){ printf("int_storage: out of memory!\n"); exit(0); @@ -242,7 +242,7 @@ int inter_storage_init() } while(fgets(line,65535,fp)){ sscanf(line,"%d",&tmp_int); - s=calloc(sizeof(struct storage), 1); + s = (struct storage*)aCalloc(sizeof(struct storage), 1); if(s==NULL){ printf("int_storage: out of memory!\n"); exit(0); @@ -254,7 +254,7 @@ int inter_storage_init() } else{ printf("int_storage: broken data [%s] line %d\n",storage_txt,c); - free(s); + aFree(s); } c++; } @@ -270,7 +270,7 @@ int inter_storage_init() } while(fgets(line,65535,fp)){ sscanf(line,"%d",&tmp_int); - gs=calloc(sizeof(struct guild_storage), 1); + gs = (struct guild_storage*)aCalloc(sizeof(struct guild_storage), 1); if(gs==NULL){ printf("int_storage: out of memory!\n"); exit(0); @@ -282,7 +282,7 @@ int inter_storage_init() } else{ printf("int_storage: broken data [%s] line %d\n",guild_storage_txt,c); - free(gs); + aFree(gs); } c++; } @@ -291,6 +291,22 @@ int inter_storage_init() return 0; } +int storage_db_final (void *k, void *data, va_list ap) { + struct storage *p = (struct storage *) data; + if (p) aFree(p); + return 0; +} +int guild_storage_db_final (void *k, void *data, va_list ap) { + struct guild_storage *p = (struct guild_storage *) data; + if (p) aFree(p); + return 0; +} +void inter_storage_final() { + numdb_final(storage_db, storage_db_final); + numdb_final(guild_storage_db, guild_storage_db_final); + return; +} + int inter_storage_save_sub(void *key,void *data,va_list ap) { char line[65536]; @@ -348,15 +364,15 @@ int inter_guild_storage_save() // ‘qŒÉƒf[ƒ^íœ int inter_storage_delete(int account_id) { - struct storage *s = numdb_search(storage_db,account_id); + struct storage *s = (struct storage *) numdb_search(storage_db,account_id); if(s) { int i; for(i=0;i<s->storage_amount;i++){ - if(s->storage[i].card[0] == (short)0xff00) - inter_pet_delete(*((long *)(&s->storage[i].card[2]))); + if(s->storage_[i].card[0] == (short)0xff00) + inter_pet_delete(*((long *)(&s->storage_[i].card[2]))); } numdb_erase(storage_db,account_id); - free(s); + aFree(s); } return 0; } @@ -364,15 +380,15 @@ int inter_storage_delete(int account_id) // ƒMƒ‹ƒh‘qŒÉƒf[ƒ^íœ int inter_guild_storage_delete(int guild_id) { - struct guild_storage *gs = numdb_search(guild_storage_db,guild_id); + struct guild_storage *gs = (struct guild_storage *) numdb_search(guild_storage_db,guild_id); if(gs) { int i; for(i=0;i<gs->storage_amount;i++){ - if(gs->storage[i].card[0] == (short)0xff00) - inter_pet_delete(*((long *)(&gs->storage[i].card[2]))); + if(gs->storage_[i].card[0] == (short)0xff00) + inter_pet_delete(*((long *)(&gs->storage_[i].card[2]))); } numdb_erase(guild_storage_db,guild_id); - free(gs); + aFree(gs); } return 0; } diff --git a/src/char/int_storage.h b/src/char/int_storage.h index d918f5fe3..f228be53d 100644 --- a/src/char/int_storage.h +++ b/src/char/int_storage.h @@ -3,6 +3,7 @@ #define _INT_STORAGE_H_ int inter_storage_init(); +void inter_storage_final(); int inter_storage_save(); int inter_guild_storage_save(); int inter_storage_delete(int account_id); diff --git a/src/char/inter.c b/src/char/inter.c index bf7bdcccf..0dca38559 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -47,7 +47,7 @@ int inter_send_packet_length[] = { int inter_recv_packet_length[] = { -1,-1, 7,-1, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, - 72, 6,52,14, 10,29, 6,-1, 34, 0, 0, 0, 0, 0, 0, 0, + 74, 6,52,14, 10,29, 6,-1, 34, 0, 0, 0, 0, 0, 0, 0, -1, 6,-1, 0, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1, 5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -114,7 +114,7 @@ int inter_accreg_init() { while(fgets(line, sizeof(line)-1, fp)){ line[sizeof(line)-1] = '\0'; - reg = calloc(sizeof(struct accreg), 1); + reg = (struct accreg*)aCalloc(sizeof(struct accreg), 1); if (reg == NULL) { printf("inter: accreg: out of memory!\n"); exit(0); @@ -123,7 +123,7 @@ int inter_accreg_init() { numdb_insert(accreg_db, reg->account_id, reg); } else { printf("inter: accreg: broken data [%s] line %d\n", accreg_txt, c); - free(reg); + aFree(reg); } c++; } @@ -261,6 +261,29 @@ int inter_init(const char *file) { return 0; } +// finalize +int accreg_db_final (void *k, void *data, va_list ap) { + struct accreg *p = (struct accreg *) data; + if (p) aFree(p); + return 0; +} +int wis_db_final (void *k, void *data, va_list ap) { + struct WisData *p = (struct WisData *) data; + if (p) aFree(p); + return 0; +} +void inter_final() { + numdb_final(accreg_db, accreg_db_final); + numdb_final(wis_db, wis_db_final); + + inter_party_final(); + inter_guild_final(); + inter_storage_final(); + inter_pet_final(); + + return; +} + // ƒ}ƒbƒvƒT[ƒo[Ú‘± int inter_mapif_init(int fd) { inter_guild_mapif_init(fd); @@ -272,13 +295,13 @@ int inter_mapif_init(int fd) { // sended packets to map-server // GMƒƒbƒZ[ƒW‘—M -int mapif_GMmessage(unsigned char *mes, int len) { - unsigned char buf[len]; +int mapif_GMmessage(unsigned char *mes, int len, int sfd) { + unsigned char buf[2048]; WBUFW(buf,0) = 0x3800; WBUFW(buf,2) = len; memcpy(WBUFP(buf,4), mes, len - 4); - mapif_sendall(buf, len); + mapif_sendallwos(sfd, buf, len); // printf("inter server: GM:%d %s\n", len, mes); return 0; @@ -286,7 +309,7 @@ int mapif_GMmessage(unsigned char *mes, int len) { // Wisp/page transmission to all map-server int mapif_wis_message(struct WisData *wd) { - unsigned char buf[56 + wd->len]; + unsigned char buf[2048]; WBUFW(buf, 0) = 0x3801; WBUFW(buf, 2) = 56 + wd->len; @@ -314,7 +337,7 @@ int mapif_wis_end(struct WisData *wd, int flag) { // ƒAƒJƒEƒ“ƒg•Ï”‘—M int mapif_account_reg(int fd, unsigned char *src) { - unsigned char buf[WBUFW(src,2)]; + unsigned char buf[2048]; memcpy(WBUFP(buf,0),src,WBUFW(src,2)); WBUFW(buf, 0) = 0x3804; @@ -325,7 +348,7 @@ int mapif_account_reg(int fd, unsigned char *src) { // ƒAƒJƒEƒ“ƒg•Ï”—v‹•ÔM int mapif_account_reg_reply(int fd,int account_id) { - struct accreg *reg = numdb_search(accreg_db,account_id); + struct accreg *reg = (struct accreg*)numdb_search(accreg_db,account_id); WFIFOW(fd,0) = 0x3804; WFIFOL(fd,4) = account_id; @@ -366,12 +389,12 @@ int check_ttl_wisdata() { wis_delnum = 0; numdb_foreach(wis_db, check_ttl_wisdata_sub, tick); for(i = 0; i < wis_delnum; i++) { - struct WisData *wd = numdb_search(wis_db, wis_dellist[i]); + struct WisData *wd = (struct WisData*)numdb_search(wis_db, wis_dellist[i]); printf("inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst); // removed. not send information after a timeout. Just no answer for the player //mapif_wis_end(wd, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target numdb_erase(wis_db, wd->id); - free(wd); + aFree(wd); } } while(wis_delnum >= WISDELLIST_MAX); @@ -383,7 +406,7 @@ int check_ttl_wisdata() { // GMƒƒbƒZ[ƒW‘—M int mapif_parse_GMmessage(int fd) { - mapif_GMmessage(RFIFOP(fd,4), RFIFOW(fd,2)); + mapif_GMmessage(RFIFOP(fd,4), RFIFOW(fd,2), fd); return 0; } @@ -403,7 +426,7 @@ int mapif_parse_WisRequest(int fd) { } // search if character exists before to ask all map-servers - if ((index = search_character_index(RFIFOP(fd,28))) == -1) { + if ((index = search_character_index((char*)RFIFOP(fd,28))) == -1) { unsigned char buf[27]; WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), 24); @@ -413,9 +436,9 @@ int mapif_parse_WisRequest(int fd) { } else { // to be sure of the correct name, rewrite it memset(RFIFOP(fd,28), 0, 24); - strncpy(RFIFOP(fd,28), search_character_name(index), 24); + strncpy((char*)RFIFOP(fd,28), search_character_name(index), 24); // if source is destination, don't ask other servers. - if (strcmp(RFIFOP(fd,4),RFIFOP(fd,28)) == 0) { + if (strcmp((char*)RFIFOP(fd,4),(char*)RFIFOP(fd,28)) == 0) { unsigned char buf[27]; WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), 24); @@ -423,7 +446,7 @@ int mapif_parse_WisRequest(int fd) { mapif_send(fd, buf, 27); } else { - wd = (struct WisData *)calloc(sizeof(struct WisData), 1); + wd = (struct WisData *)aCalloc(sizeof(struct WisData), 1); if (wd == NULL){ printf("inter: WisRequest: out of memory !\n"); return 0; @@ -450,7 +473,7 @@ int mapif_parse_WisRequest(int fd) { // Wisp/page transmission result int mapif_parse_WisReply(int fd) { int id = RFIFOL(fd,2), flag = RFIFOB(fd,6); - struct WisData *wd = numdb_search(wis_db, id); + struct WisData *wd = (struct WisData*)numdb_search(wis_db, id); if (wd == NULL) return 0; // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server @@ -458,7 +481,7 @@ int mapif_parse_WisReply(int fd) { if ((--wd->count) <= 0 || flag != 1) { mapif_wis_end(wd, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target numdb_erase(wis_db, id); - free(wd); + aFree(wd); } return 0; @@ -466,7 +489,7 @@ int mapif_parse_WisReply(int fd) { // Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers) int mapif_parse_WisToGM(int fd) { - unsigned char buf[RFIFOW(fd,2)]; // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B + unsigned char buf[2048]; // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2)); WBUFW(buf, 0) = 0x3803; @@ -478,10 +501,10 @@ int mapif_parse_WisToGM(int fd) { // ƒAƒJƒEƒ“ƒg•Ï”•Û‘¶—v‹ int mapif_parse_AccReg(int fd) { int j, p; - struct accreg *reg = numdb_search(accreg_db, RFIFOL(fd,4)); + struct accreg *reg = (struct accreg*)numdb_search(accreg_db, RFIFOL(fd,4)); if (reg == NULL) { - if ((reg = calloc(sizeof(struct accreg), 1)) == NULL) { + if ((reg = (struct accreg*)aCalloc(sizeof(struct accreg), 1)) == NULL) { printf("inter: accreg: out of memory !\n"); exit(0); } diff --git a/src/char/inter.h b/src/char/inter.h index 0b6f809d7..636ce31d8 100644 --- a/src/char/inter.h +++ b/src/char/inter.h @@ -3,6 +3,7 @@ #define _INTER_H_ int inter_init(const char *file); +void inter_final(); int inter_save(); int inter_parse_frommap(int fd); int inter_mapif_init(int fd); diff --git a/src/char_sql/GNUmakefile b/src/char_sql/GNUmakefile deleted file mode 100644 index 0f25010d8..000000000 --- a/src/char_sql/GNUmakefile +++ /dev/null @@ -1,20 +0,0 @@ -all: char-server_sql -sql: char-server_sql - -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o ../common/utils.o ../common/nullpo.o -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/nullpo.h - -char-server_sql: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o strlib.o itemdb.o $(COMMON_OBJ) - $(CC) -o ../../$@ $^ $(LIB_S) - -char.o: char.c char.h strlib.h itemdb.h ../common/showmsg.h -inter.o: inter.c inter.h int_party.h int_guild.h int_storage.h int_pet.h ../common/mmo.h char.h ../common/socket.h ../common/showmsg.h -int_party.o: int_party.c int_party.h inter.h ../common/mmo.h char.h ../common/socket.h ../common/timer.h ../common/db.h ../common/showmsg.h -int_guild.o: int_guild.c int_guild.h inter.h ../common/mmo.h char.h ../common/socket.h ../common/db.h ../common/showmsg.h -int_storage.o: int_storage.c int_storage.h char.h itemdb.h ../common/showmsg.h -int_pet.o: int_pet.c int_pet.h inter.h char.h ../common/mmo.h ../common/socket.h ../common/db.h ../common/showmsg.h -strlib.o: strlib.c strlib.h ../common/showmsg.h -itemdb.o: itemdb.c itemdb.h ../common/db.h ../common/mmo.h ../common/showmsg.h - -clean: - rm -f *.o ../../char-server_sql
\ No newline at end of file diff --git a/src/char_sql/Makefile b/src/char_sql/Makefile index 0f25010d8..1741b5ab6 100644 --- a/src/char_sql/Makefile +++ b/src/char_sql/Makefile @@ -1,20 +1,20 @@ all: char-server_sql sql: char-server_sql -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o ../common/utils.o ../common/nullpo.o -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/nullpo.h +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o ../common/obj/strlib.o +COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h -char-server_sql: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o strlib.o itemdb.o $(COMMON_OBJ) +char-server_sql: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o itemdb.o $(COMMON_OBJ) $(CC) -o ../../$@ $^ $(LIB_S) -char.o: char.c char.h strlib.h itemdb.h ../common/showmsg.h +char.o: char.c char.h ../common/strlib.h itemdb.h ../common/showmsg.h inter.o: inter.c inter.h int_party.h int_guild.h int_storage.h int_pet.h ../common/mmo.h char.h ../common/socket.h ../common/showmsg.h int_party.o: int_party.c int_party.h inter.h ../common/mmo.h char.h ../common/socket.h ../common/timer.h ../common/db.h ../common/showmsg.h int_guild.o: int_guild.c int_guild.h inter.h ../common/mmo.h char.h ../common/socket.h ../common/db.h ../common/showmsg.h int_storage.o: int_storage.c int_storage.h char.h itemdb.h ../common/showmsg.h int_pet.o: int_pet.c int_pet.h inter.h char.h ../common/mmo.h ../common/socket.h ../common/db.h ../common/showmsg.h -strlib.o: strlib.c strlib.h ../common/showmsg.h itemdb.o: itemdb.c itemdb.h ../common/db.h ../common/mmo.h ../common/showmsg.h +$(COMMON_OBJ): $(COMMON_H) clean: - rm -f *.o ../../char-server_sql
\ No newline at end of file + rm -f *.o ../../char-server_sql diff --git a/src/char_sql/char.c b/src/char_sql/char.c index 91bc604a3..d672bc0eb 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -18,8 +18,6 @@ #include <netdb.h> #endif -#include "../common/utils.h" -#include "../common/nullpo.h" #include <stdio.h> #include <stdlib.h> #include <netinet/in.h> @@ -35,15 +33,18 @@ #include <stdarg.h> #include "char.h" -#include "strlib.h" +#include "../common/utils.h" +#include "../common/strlib.h" #include "itemdb.h" #include "inter.h" +#include "db.h" +#include "malloc.h" #ifdef MEMWATCH #include "memwatch.h" #endif -#define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y) +static struct dbt *char_db_; char char_db[256] = "char"; char cart_db[256] = "cart_inventory"; @@ -65,22 +66,18 @@ char guild_storage_db[256] = "guild_storage"; char party_db[256] = "party"; char pet_db[256] = "pet"; char login_db[256] = "login"; +char friend_db[256] = "friends"; +int db_use_sqldbs; char login_db_account_id[32] = "account_id"; char login_db_level[32] = "level"; int lowest_gm_level = 1; -int user_count_timer; - -unsigned char *SQL_CONF_NAME = "conf/inter_athena.conf"; +char *SQL_CONF_NAME = "conf/inter_athena.conf"; struct mmo_map_server server[MAX_MAP_SERVERS]; int server_fd[MAX_MAP_SERVERS]; -int server_freezeflag[MAX_MAP_SERVERS]; // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed - -int anti_freeze_enable = 0; -int ANTI_FREEZE_INTERVAL = 6; int login_fd, char_fd; char userid[24]; @@ -89,17 +86,21 @@ char server_name[20]; char wisp_server_name[24] = "Server"; int login_ip_set_ = 0; char login_ip_str[128]; -int login_ip; +in_addr_t login_ip; int login_port = 6900; int char_ip_set_ = 0; char char_ip_str[128]; -int char_ip; +int bind_ip_set_ = 0; +char bind_ip_str[128]; +in_addr_t char_ip; int char_port = 6121; int char_maintenance; int char_new; int name_ignoring_case = 0; // Allow or not identical name for characters but with a different case by [Yor] int char_name_option = 0; // Option to know which letters/symbols are authorised in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor] char char_name_letters[1024] = ""; // list of letters/symbols used to authorise or not a name of a character. by [Yor] +int char_per_account = 0; //Maximum charas per account (default unlimited) [Sirius] + int log_char = 1; // loggin char or not [devil] int log_inter = 1; // loggin inter or not [devil] @@ -132,10 +133,11 @@ int auth_fifo_pos = 0; int check_ip_flag = 1; // It's to check IP of a player between char-server and other servers (part of anti-hacking system) -//int char_id_count = 150000; // no longer needed, use of MIN_CHAR_ID instead [Ajarn] +//int char_id_count = 150000; //removed by [Sirius] for new charcreate issue (auto_increment @sql) struct mmo_charstatus *char_dat; int char_num,char_max; int max_connect_user = 0; +int gm_allow_level = 99; int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; int start_zeny = 500; int start_weapon = 1201; @@ -154,49 +156,77 @@ int GM_num = 0; int console = 0; -char prev_query[65535]; +#define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y) -char servers_connected = 0; +//------------------------------------------------- +// Set Character online/offline [Wizputer] +//------------------------------------------------- -// GM Database -struct dbt *gm_db; +void set_char_online(int char_id, int account_id) { + if ( char_id != 99 ) { + sprintf(tmp_sql, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d'",char_db,char_id); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (set char online)- %s\n", mysql_error(&mysql_handle)); + } + } -//---------------------------------------------- -//SQL Commands ( Original by Clownisius ) [Edit: Wizputer] -//---------------------------------------------- + if (login_fd <= 0 || session[login_fd]->eof) + return; + WFIFOW(login_fd,0) = 0x272b; + WFIFOL(login_fd,2) = account_id; + WFIFOSET(login_fd,6); -void sql_query(char* query,char function[32]) { - if(mysql_query(&mysql_handle, query)){ - printf("---------- SQL error report ----------\n"); - printf("MySQL Server Error: %s\n", mysql_error(&mysql_handle)); - printf("Query: %s\n", query); - printf("In function: %s \n", function); - printf("\nPrevious query: %s\n", prev_query); -// if (strcmp(mysql_error(&mysql_handle),"CR_COMMANDS_OUT_OF_SYNC") !=0) printf(" - = Shutting down Char Server = - \n\n"); - printf("-------- End SQL Error Report --------\n"); -// printf("Uncontrolled param: %s",&mysql_handle); -// if (strcmp(mysql_error(&mysql_handle),"CR_COMMANDS_OUT_OF_SYNC") !=0) exit(1); +} + +void set_all_offline(void) { + sprintf(tmp_sql, "SELECT `account_id` FROM `%s` WHERE `online`='1'",char_db); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select all online)- %s\n", mysql_error(&mysql_handle)); } + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { + while((sql_row = mysql_fetch_row(sql_res))) { + if ( login_fd > 0 ) { + printf("send user offline: %d\n",atoi(sql_row[0])); + WFIFOW(login_fd,0) = 0x272c; + WFIFOL(login_fd,2) = atoi(sql_row[0]); + WFIFOSET(login_fd,6); + } + } + } - strcpy(prev_query,query); + mysql_free_result(sql_res); + sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `online`='1'", char_db); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (set_all_offline)- %s\n", mysql_error(&mysql_handle)); + } } -//----------------------------------------------------- -// Function to suppress control characters in a string. -//----------------------------------------------------- -int remove_control_chars(unsigned char *str) { - int i; - int change = 0; +void set_char_offline(int char_id, int account_id) { + struct mmo_charstatus *cp; - for(i = 0; i < strlen(str); i++) { - if (str[i] < 32) { - str[i] = '_'; - change = 1; + if ( char_id == 99 ) + sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `account_id`='%d'", char_db, account_id); + else { + cp = (struct mmo_charstatus*)numdb_search(char_db_,char_id); + if (cp != NULL) { + aFree(cp); + numdb_erase(char_db_,char_id); } + + sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `char_id`='%d'", char_db, char_id); + + if (mysql_query(&mysql_handle, tmp_sql)) + printf("DB server Error (set_char_offline)- %s\n", mysql_error(&mysql_handle)); } - return change; + if (login_fd <= 0 || session[login_fd]->eof) + return; + + WFIFOW(login_fd,0) = 0x272c; + WFIFOL(login_fd,2) = account_id; + WFIFOSET(login_fd,6); } //---------------------------------------------------------------------- @@ -204,161 +234,214 @@ int remove_control_chars(unsigned char *str) { // and returns its level (or 0 if it isn't a GM account or if not found) //---------------------------------------------------------------------- // Removed since nothing GM related goes on in the char server [CLOWNISIUS] +int isGM(int account_id) { + int i; -unsigned char isGM(int account_id) { - unsigned char *level; - - level = numdb_search(gm_db, account_id); - if (level == NULL) - return 0; - - return *level; -} - -static int gmdb_final(void *key,void *data,va_list ap) { - unsigned char *level; - - nullpo_retr(0, level=data); - - free(level); - + for(i = 0; i < GM_num; i++) + if (gm_account[i].account_id == account_id) + return gm_account[i].level; return 0; } -void do_final_gmdb(void) { - if(gm_db){ - numdb_final(gm_db,gmdb_final); - gm_db=NULL; +void read_gm_account(void) { + if (gm_account != NULL) + aFree(gm_account); + GM_num = 0; + + sprintf(tmp_lsql, "SELECT `%s`,`%s` FROM `%s` WHERE `%s`>='%d'",login_db_account_id,login_db_level,login_db,login_db_level,lowest_gm_level); + if (mysql_query(&lmysql_handle, tmp_lsql)) { + printf("DB server Error (select %s to Memory)- %s\n",login_db,mysql_error(&lmysql_handle)); + } + lsql_res = mysql_store_result(&lmysql_handle); + if (lsql_res) { + gm_account = (struct gm_account*)aCalloc(sizeof(struct gm_account) * mysql_num_rows(lsql_res), 1); + while ((lsql_row = mysql_fetch_row(lsql_res))) { + gm_account[GM_num].account_id = atoi(lsql_row[0]); + gm_account[GM_num].level = atoi(lsql_row[1]); + GM_num++; + } } -} - -int read_gm_accounts(int fd, int len) { - GM_num = RFIFOW(fd,2); - - if(len < (6+5*GM_num)) - return -1; - int i=0,account_id=0; - unsigned char *level; - - if (gm_db) - do_final_gmdb(); + mysql_free_result(lsql_res); + mapif_send_gmaccounts(); +} - gm_db = numdb_init(); +// Insert friends list +int insert_friends(int char_id){ + int i; + char *tmp_p = tmp_sql; - WFIFOW(fd,0) = 0x2b99; - WFIFOW(fd,2) = GM_num; + tmp_p += sprintf(tmp_p, "REPLACE INTO `%s` (`id`, `account_id`",friend_db); - if(GM_num) { - for(i=0;i<GM_num;i++) { - level = malloc(sizeof(unsigned char)); + for (i=0;i<20;i++) + tmp_p += sprintf(tmp_p, ", `friend_id%d`, `name%d`", i, i); - *level = RFIFOB(fd,(10+5*(GM_num-1))); - account_id = RFIFOW(fd,(6+5*(GM_num-1))); + tmp_p += sprintf(tmp_p, ") VALUES (NULL, '%d'", char_id); - numdb_insert(gm_db, account_id, level); + for (i=0;i<20;i++) + tmp_p += sprintf(tmp_p, ", '0', ''"); - WFIFOL(fd,6+5*i) = account_id; - WFIFOB(fd,10+5*i) = *level; - } - } + tmp_p += sprintf(tmp_p, ")"); - WFIFOSET(fd,6+5*i); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (insert `friend`)- %s\n", mysql_error(&mysql_handle)); + return 0; + } +return 1; +} - return 0; +int compare_item(struct item *a, struct item *b) { + return ( + (a->id == b->id) && + (a->nameid == b->nameid) && + (a->amount == b->amount) && + (a->equip == b->equip) && + (a->identify == b->identify) && + (a->refine == b->refine) && + (a->attribute == b->attribute) && + (a->card[0] == b->card[0]) && + (a->card[1] == b->card[1]) && + (a->card[2] == b->card[2]) && + (a->card[3] == b->card[3])); } //===================================================================================================== int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ - int i=0; - int eqcount=1; - char temp_str[32]; + int i=0,party_exist,guild_exist; +// int eqcount=1; +// int noteqcount=1; + int count = 0; + int diff = 0; + char temp_str[1024]; + char *tmp_p = tmp_sql; + struct mmo_charstatus *cp; + struct itemtmp mapitem[MAX_GUILD_STORAGE]; - struct itemtemp mapitem; if (char_id!=p->char_id) return 0; - save_flag = p->char_id; + cp = (struct mmo_charstatus*)numdb_search(char_db_,char_id); - #ifdef DEBUG + if (cp == NULL) { + cp = (struct mmo_charstatus *) aMalloc(sizeof(struct mmo_charstatus)); + memset(cp, 0, sizeof(struct mmo_charstatus)); + numdb_insert(char_db_, char_id,cp); + } + + save_flag = p->char_id; printf("(\033[1;32m%d\033[0m) %s \trequest save char data - ",char_id,char_dat[0].name); - #endif - sql_query("START TRANSACTION","mmo_char_tosql"); +//for(testcount=1;testcount<50;testcount++){//---------------------------test count-------------------- +// printf("test count : %d\n", testcount); +// eqcount=1; +// noteqcount=1; +// dbeqcount=1; +// dbnoteqcount=1; +//----------------------------------------------------------------------------------------------------- //=========================================map inventory data > memory =============================== + diff = 0; + //map inventory data for(i=0;i<MAX_INVENTORY;i++){ + if (!compare_item(&p->inventory[i], &cp->inventory[i])) + diff = 1; if(p->inventory[i].nameid>0){ - mapitem.equip[eqcount].flag=0; - mapitem.equip[eqcount].id = p->inventory[i].id; - mapitem.equip[eqcount].nameid=p->inventory[i].nameid; - mapitem.equip[eqcount].amount = p->inventory[i].amount; - mapitem.equip[eqcount].equip = p->inventory[i].equip; - mapitem.equip[eqcount].identify = p->inventory[i].identify; - mapitem.equip[eqcount].refine = p->inventory[i].refine; - mapitem.equip[eqcount].attribute = p->inventory[i].attribute; - mapitem.equip[eqcount].card[0] = p->inventory[i].card[0]; - mapitem.equip[eqcount].card[1] = p->inventory[i].card[1]; - mapitem.equip[eqcount].card[2] = p->inventory[i].card[2]; - mapitem.equip[eqcount].card[3] = p->inventory[i].card[3]; - eqcount++; + mapitem[count].flag=0; + mapitem[count].id = p->inventory[i].id; + mapitem[count].nameid=p->inventory[i].nameid; + mapitem[count].amount = p->inventory[i].amount; + mapitem[count].equip = p->inventory[i].equip; + mapitem[count].identify = p->inventory[i].identify; + mapitem[count].refine = p->inventory[i].refine; + mapitem[count].attribute = p->inventory[i].attribute; + mapitem[count].card[0] = p->inventory[i].card[0]; + mapitem[count].card[1] = p->inventory[i].card[1]; + mapitem[count].card[2] = p->inventory[i].card[2]; + mapitem[count].card[3] = p->inventory[i].card[3]; + count++; } } - - memitemdata_to_sql2(mapitem, eqcount, p->char_id,TABLE_INVENTORY); - - #ifdef DEBUG - printf("Char [%s] - Save item data to SQL!\n",p->name); - #endif + //printf("- Save item data to MySQL!\n"); + if (diff) + memitemdata_to_sql(mapitem, count, p->char_id,TABLE_INVENTORY); //=========================================map cart data > memory ==================================== - eqcount=1; +// eqcount=1; +// noteqcount=1; + count = 0; + diff = 0; //map cart data for(i=0;i<MAX_CART;i++){ + if (!compare_item(&p->cart[i], &cp->cart[i])) + diff = 1; if(p->cart[i].nameid>0){ - mapitem.equip[eqcount].flag=0; - mapitem.equip[eqcount].id = p->cart[i].id; - mapitem.equip[eqcount].nameid=p->cart[i].nameid; - mapitem.equip[eqcount].amount = p->cart[i].amount; - mapitem.equip[eqcount].equip = p->cart[i].equip; - mapitem.equip[eqcount].identify = p->cart[i].identify; - mapitem.equip[eqcount].refine = p->cart[i].refine; - mapitem.equip[eqcount].attribute = p->cart[i].attribute; - mapitem.equip[eqcount].card[0] = p->cart[i].card[0]; - mapitem.equip[eqcount].card[1] = p->cart[i].card[1]; - mapitem.equip[eqcount].card[2] = p->cart[i].card[2]; - mapitem.equip[eqcount].card[3] = p->cart[i].card[3]; - eqcount++; + mapitem[count].flag=0; + mapitem[count].id = p->cart[i].id; + mapitem[count].nameid=p->cart[i].nameid; + mapitem[count].amount = p->cart[i].amount; + mapitem[count].equip = p->cart[i].equip; + mapitem[count].identify = p->cart[i].identify; + mapitem[count].refine = p->cart[i].refine; + mapitem[count].attribute = p->cart[i].attribute; + mapitem[count].card[0] = p->cart[i].card[0]; + mapitem[count].card[1] = p->cart[i].card[1]; + mapitem[count].card[2] = p->cart[i].card[2]; + mapitem[count].card[3] = p->cart[i].card[3]; + count++; } } - memitemdata_to_sql2(mapitem, eqcount, p->char_id,TABLE_CART); + //printf("- Save cart data to MySQL!\n"); + if (diff) + memitemdata_to_sql(mapitem, count, p->char_id,TABLE_CART); - #ifdef DEBUG - printf("Char [%s] - Save cart data to SQL!\n",p->name); - #endif +//===================================================================================================== + if ((p->base_exp != cp->base_exp) || (p->class_ != cp->class_) || + (p->base_level != cp->base_level) || (p->job_level != cp->job_level) || + (p->job_exp != cp->job_exp) || (p->zeny != cp->zeny) || + (p->last_point.x != cp->last_point.x) || (p->last_point.y != cp->last_point.y) || + (p->max_hp != cp->max_hp) || (p->hp != cp->hp) || + (p->max_sp != cp->max_sp) || (p->sp != cp->sp) || + (p->status_point != cp->status_point) || (p->skill_point != cp->skill_point) || + (p->str != cp->str) || (p->agi != cp->agi) || (p->vit != cp->vit) || + (p->int_ != cp->int_) || (p->dex != cp->dex) || (p->luk != cp->luk) || + (p->option != cp->option) || (p->karma != cp->karma) || (p->manner != cp->manner) || + (p->party_id != cp->party_id) || (p->guild_id != cp->guild_id) || + (p->pet_id != cp->pet_id) || (p->hair != cp->hair) || (p->hair_color != cp->hair_color) || + (p->clothes_color != cp->clothes_color) || (p->weapon != cp->weapon) || + (p->shield != cp->shield) || (p->head_top != cp->head_top) || + (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || + (p->partner_id != cp->partner_id) || (p->father != cp->father) || + (p->mother != cp->mother) || (p->child != cp->child)) { + +//}//---------------------------test count------------------------------ //check party_exist - sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `party_id` = '%d'",party_db, p->party_id); - sql_query(tmp_sql,"mmo_char_tosql"); - - if((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) - if(!atoi(sql_row[0])) - p->party_id=0; - + party_exist=0; + sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `party_id` = '%d'",party_db, p->party_id); // TBR + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + sql_row = mysql_fetch_row(sql_res); + if (sql_row) party_exist = atoi(sql_row[0]); mysql_free_result(sql_res); //check guild_exist - sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `guild_id` = '%d'",guild_db, p->guild_id); - sql_query(tmp_sql,"mmo_char_tosql"); - - if((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) - if(!atoi(sql_row[0])) - p->guild_id=0; - + guild_exist=0; + sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `guild_id` = '%d'",guild_db, p->guild_id); // TBR + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + sql_row = mysql_fetch_row(sql_res); + if (sql_row) guild_exist = atoi(sql_row[0]); mysql_free_result(sql_res); + if (guild_exist==0) p->guild_id=0; + if (party_exist==0) p->party_id=0; + //sql query //`char`( `char_id`,`account_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`, //9 //`str`,`agi`,`vit`,`int`,`dex`,`luk`, //15 @@ -373,8 +456,8 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ "`str`='%d',`agi`='%d',`vit`='%d',`int`='%d',`dex`='%d',`luk`='%d'," "`option`='%d',`karma`='%d',`manner`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d'," "`hair`='%d',`hair_color`='%d',`clothes_color`='%d',`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," - "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d',`partner_id`='%d' WHERE `account_id`='%d' AND `char_id` = '%d'", - char_db, p->class, p->base_level, p->job_level, + "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d',`partner_id`='%d', `father`='%d', `mother`='%d', `child`='%d' WHERE `account_id`='%d' AND `char_id` = '%d'", + char_db, p->class_, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, p->max_hp, p->hp, p->max_sp, p->sp, p->status_point, p->skill_point, p->str, p->agi, p->vit, p->int_, p->dex, p->luk, @@ -382,351 +465,252 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ p->hair, p->hair_color, p->clothes_color, p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom, p->last_point.map, p->last_point.x, p->last_point.y, - p->save_point.map, p->save_point.x, p->save_point.y, p->partner_id, p->account_id, p->char_id + p->save_point.map, p->save_point.x, p->save_point.y, p->partner_id, p->father, p->mother, + p->child, p->account_id, p->char_id ); - sql_query(tmp_sql,"mmo_char_tosql"); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle)); + } - #ifdef DEBUG - printf("Char [%s] - Saved Char data to SQL!\n",p->name); - #endif + } - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",memo_db,char_id); - sql_query(tmp_sql,"mmo_char_tosql"); + diff = 0; - sprintf(tmp_sql,"INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ",memo_db); for(i=0;i<10;i++){ - if(i) - sprintf(tmp_sql,"%s,",tmp_sql); + if((strcmp(p->memo_point[i].map,cp->memo_point[i].map) == 0) && (p->memo_point[i].x == cp->memo_point[i].x) && (p->memo_point[i].y == cp->memo_point[i].y)) + continue; + diff = 1; + break; + } - if(p->memo_point[i].map[0]) - sprintf(tmp_sql,"%s('%d', '%s', '%d', '%d')",tmp_sql, - char_id, p->memo_point[i].map, p->memo_point[i].x, p->memo_point[i].y); + if (diff) { + //printf("- Save memo data to MySQL!\n"); + //`memo` (`memo_id`,`char_id`,`map`,`x`,`y`) + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",memo_db, p->char_id); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (delete `memo`)- %s\n", mysql_error(&mysql_handle)); } - sql_query(tmp_sql,"mmo_char_tosql"); + //insert here. + for(i=0;i<10;i++){ + if(p->memo_point[i].map[0]){ + sprintf(tmp_sql,"INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ('%d', '%s', '%d', '%d')", + memo_db, char_id, p->memo_point[i].map, p->memo_point[i].x, p->memo_point[i].y); + if(mysql_query(&mysql_handle, tmp_sql)) + printf("DB server Error (insert `memo`)- %s\n", mysql_error(&mysql_handle)); + } + } + } - #ifdef DEBUG - printf("Char [%s] - Saved memo data to SQL!\n",p->name); - #endif + diff = 0; + for(i=0;i<MAX_SKILL;i++) { + if ((p->skill[i].lv != 0) && (p->skill[i].id == 0)) + p->skill[i].id = i; // Fix skill tree - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",skill_db,char_id); - sql_query(tmp_sql,"mmo_char_tosql"); + if((p->skill[i].id != cp->skill[i].id) || (p->skill[i].lv != cp->skill[i].lv) || + (p->skill[i].flag != cp->skill[i].flag)) { + diff = 1; + break; + } + } - sprintf(tmp_sql,"INSERT INTO `%s`(`char_id`, `id`, `lv`) VALUES ",skill_db); + if (diff) { + //printf("- Save skill data to MySQL!\n"); + //`skill` (`char_id`, `id`, `lv`) + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",skill_db, p->char_id); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (delete `skill`)- %s\n", mysql_error(&mysql_handle)); + } + //printf("- Insert skill \n"); + //insert here. for(i=0;i<MAX_SKILL;i++){ if(p->skill[i].id){ if (p->skill[i].id && p->skill[i].flag!=1) { - if(i) - sprintf(tmp_sql,"%s,",tmp_sql); - - sprintf(tmp_sql,"%s('%d', '%d','%d')",tmp_sql, - char_id, p->skill[i].id, (p->skill[i].flag==0)?p->skill[i].lv:p->skill[i].flag-2); + sprintf(tmp_sql,"INSERT INTO `%s`(`char_id`, `id`, `lv`) VALUES ('%d', '%d','%d')", + skill_db, char_id, p->skill[i].id, (p->skill[i].flag==0)?p->skill[i].lv:p->skill[i].flag-2); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (insert `skill`)- %s\n", mysql_error(&mysql_handle)); + } } } } + } - sql_query(tmp_sql,"mmo_char_tosql"); - - #ifdef DEBUG - printf("Char [%s] - Save skill data to SQL!\n",p->name); - #endif + diff = 0; + for(i=0;i<p->global_reg_num;i++) { + if ((p->global_reg[i].str == NULL) && (cp->global_reg[i].str == NULL)) + continue; + if (((p->global_reg[i].str == NULL) != (cp->global_reg[i].str == NULL)) || + (p->global_reg[i].value != cp->global_reg[i].value) || + strcmp(p->global_reg[i].str, cp->global_reg[i].str) != 0) { + diff = 1; + break; + } + } - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d' AND `type`='3'",reg_db,char_id); - sql_query(tmp_sql,"mmo_char_tosql"); + if (diff) { + //printf("- Save global_reg_value data to MySQL!\n"); + //`global_reg_value` (`char_id`, `str`, `value`) + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, p->char_id); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (delete `global_reg_value`)- %s\n", mysql_error(&mysql_handle)); + } - sprintf(tmp_sql,"INSERT INTO `%s`(`char_id`, `str`, `value`) VALUES ",reg_db); + //insert here. for(i=0;i<p->global_reg_num;i++){ if (p->global_reg[i].str) { if(p->global_reg[i].value !=0){ - if(i) - sprintf(tmp_sql,"%s,",tmp_sql); - - sprintf(tmp_sql,"%s('%d', '%s','%d')",tmp_sql, - char_id, jstrescapecpy(temp_str,(unsigned char*)p->global_reg[i].str), p->global_reg[i].value); + sprintf(tmp_sql,"INSERT INTO `%s` (`char_id`, `str`, `value`) VALUES ('%d', '%s','%d')", + reg_db, char_id, jstrescapecpy(temp_str,p->global_reg[i].str), p->global_reg[i].value); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (insert `global_reg_value`)- %s\n", mysql_error(&mysql_handle)); + } } } } + } - sql_query(tmp_sql,"mmo_char_tosql"); - - sql_query("COMMIT","mmo_char_tosql"); - - #ifdef DEBUG - printf("Char [%s] - Save global reg data to SQL!\n",p->name); - printf("Char [%s] - Saving char is done.\n",p->name); - #endif + // Friends list + // account_id, friend_id0, name0, ... + #if 0 + tmp_p += sprintf(tmp_p, "REPLACE INTO `%s` (`id`, `account_id`",friend_db); - save_flag = 0; + diff = 0; - return 0; -} + for (i=0;i<20;i++) + tmp_p += sprintf(tmp_p, ", `friend_id%d`, `name%d`", i, i); -int memitemdata_to_sql2(struct itemtemp mapitem, int eqcount, int char_id, int tableswitch){ - //equ - int i; - char tablename[16]; - char selectoption[16]; + tmp_p += sprintf(tmp_p, ") VALUES (NULL, '%d'", char_id); - switch (tableswitch){ - case TABLE_INVENTORY: - sprintf(tablename,"%s",inventory_db); - sprintf(selectoption,"char_id"); - break; - case TABLE_CART: - sprintf(tablename,"%s",cart_db); - sprintf(selectoption,"char_id"); - break; - case TABLE_STORAGE: - sprintf(tablename,"%s",storage_db); - sprintf(selectoption,"account_id"); - break; - case TABLE_GUILD_STORAGE: - sprintf(tablename,"%s",guild_storage_db); - sprintf(selectoption,"guild_id"); - break; - } - - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `%s`='%d'",tablename,selectoption,char_id); - sql_query(tmp_sql,"memitemdata_to_sql"); - - //==============================================Memory data > SQL =============================== + for (i=0;i<20;i++) { + tmp_p += sprintf(tmp_p, ", '%d', '%s'", p->friend_id[i], p->friend_name[i]); + if ((p->friend_id[i] != cp->friend_id[i]) || + strcmp(p->friend_name[i], cp->friend_name[i])) + diff = 1; + } - sprintf(tmp_sql,"INSERT INTO `%s` (`%s`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`card0`,`card1`,`card2`,`card3`) VALUES ",tablename,selectoption); + tmp_p += sprintf(tmp_p, ")"); + #else // [Dino9021] + tmp_p += sprintf(tmp_p, "UPDATE `%s` SET ",friend_db); - for(i=1;i<eqcount;i++){ - if(mapitem.equip[i].flag == 1) break; + diff = 0; + + for (i=0;i<20;i++) { + if (i>0) + tmp_p += sprintf(tmp_p, ", "); - if(i!=1) - sprintf(tmp_sql,"%s,",tmp_sql); + tmp_p += sprintf(tmp_p, "`friend_id%d`='%d', `name%d`='%s'", i, p->friend_id[i], i, p->friend_name[i]); - sprintf(tmp_sql,"%s('%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d')",tmp_sql,char_id, - mapitem.equip[i].nameid, mapitem.equip[i].amount, mapitem.equip[i].equip, mapitem.equip[i].identify, - mapitem.equip[i].refine,mapitem.equip[i].attribute, mapitem.equip[i].card[0],mapitem.equip[i].card[1], - mapitem.equip[i].card[2],mapitem.equip[i].card[3]); + if ((p->friend_id[i] != cp->friend_id[i]) || strcmp(p->friend_name[i], cp->friend_name[i])) + diff = 1; + } - mapitem.equip[i].flag=1; - } + tmp_p += sprintf(tmp_p, " where account_id='%d';", char_id); + #endif - sql_query(tmp_sql,"memitemdata_to_sql"); + if (diff) + mysql_query(&mysql_handle, tmp_sql); - #ifdef DEBUG - printf("Char [%d] - Saved Eqip Item Data to SQL!\n",char_id); - #endif + printf("saving char is done.\n"); + save_flag = 0; + memcpy(cp, p, sizeof(struct mmo_charstatus)); - return 0; + return 0; } -int memitemdata_to_sql(struct itemtemp mapitem, int eqcount, int noteqcount, int char_id, int tableswitch){ - //equ - int i, j; - int dbeqcount = 1; - int dbnoteqcount = 1; - struct itemtemp dbitem; - char tablename[16]; +// [Ilpalazzo-sama] +int memitemdata_to_sql(struct itemtmp mapitem[], int count, int char_id, int tableswitch) +{ + int i, flag, id; + char *tablename; char selectoption[16]; - switch (tableswitch){ + switch (tableswitch) { case TABLE_INVENTORY: - sprintf(tablename,"%s",inventory_db); + tablename = inventory_db; // no need for sprintf here as *_db are char*. sprintf(selectoption,"char_id"); break; case TABLE_CART: - sprintf(tablename,"%s",cart_db); + tablename = cart_db; sprintf(selectoption,"char_id"); break; case TABLE_STORAGE: - sprintf(tablename,"%s",storage_db); + tablename = storage_db; sprintf(selectoption,"account_id"); break; case TABLE_GUILD_STORAGE: - sprintf(tablename,"%s",guild_storage_db); + tablename = guild_storage_db; sprintf(selectoption,"guild_id"); break; + default: + printf("Invalid table name!\n"); + return 1; } //printf("Working Table : %s \n",tablename); //=======================================mysql database data > memory=============================================== - sprintf(tmp_sql, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3` " - "FROM `%s` WHERE `%s`='%d'",tablename ,selectoption ,char_id); + "FROM `%s` WHERE `%s`='%d'", tablename, selectoption, char_id); if (mysql_query(&mysql_handle, tmp_sql)) { printf("DB server Error (select `%s` to Memory)- %s\n",tablename ,mysql_error(&mysql_handle)); + return 1; } sql_res = mysql_store_result(&mysql_handle); if (sql_res) { - for(i=0;(sql_row = mysql_fetch_row(sql_res));i++){ - if (itemdb_isequip(atoi(sql_row[1]))==1){ - dbitem.equip[dbeqcount].flag=0; - dbitem.equip[dbeqcount].id = atoi(sql_row[0]); - dbitem.equip[dbeqcount].nameid = atoi(sql_row[1]); - dbitem.equip[dbeqcount].amount = atoi(sql_row[2]); - dbitem.equip[dbeqcount].equip = atoi(sql_row[3]); - dbitem.equip[dbeqcount].identify = atoi(sql_row[4]); - dbitem.equip[dbeqcount].refine = atoi(sql_row[5]); - dbitem.equip[dbeqcount].attribute = atoi(sql_row[6]); - dbitem.equip[dbeqcount].card[0] = atoi(sql_row[7]); - dbitem.equip[dbeqcount].card[1] = atoi(sql_row[8]); - dbitem.equip[dbeqcount].card[2] = atoi(sql_row[9]); - dbitem.equip[dbeqcount].card[3] = atoi(sql_row[10]); - dbeqcount++; - }else { - dbitem.notequip[dbnoteqcount].flag=0; - dbitem.notequip[dbnoteqcount].id = atoi(sql_row[0]); - dbitem.notequip[dbnoteqcount].nameid = atoi(sql_row[1]); - dbitem.notequip[dbnoteqcount].amount = atoi(sql_row[2]); - dbitem.notequip[dbnoteqcount].equip = atoi(sql_row[3]); - dbitem.notequip[dbnoteqcount].identify = atoi(sql_row[4]); - dbitem.notequip[dbnoteqcount].refine = atoi(sql_row[5]); - dbitem.notequip[dbnoteqcount].attribute = atoi(sql_row[6]); - dbitem.notequip[dbnoteqcount].card[0] = atoi(sql_row[7]); - dbitem.notequip[dbnoteqcount].card[1] = atoi(sql_row[8]); - dbitem.notequip[dbnoteqcount].card[2] = atoi(sql_row[9]); - dbitem.notequip[dbnoteqcount].card[3] = atoi(sql_row[10]); - dbnoteqcount++; - } - } - mysql_free_result(sql_res); - } - - //==============================================Memory data > SQL =============================== - //======================================Equip ITEM======================================= - if((eqcount==1) && (dbeqcount==1)){//printf("%s Equip Empty\n",tablename); - //item empty - } else { - - for(i=1;i<eqcount;i++){ - for(j=1;j<dbeqcount;j++){ - if(mapitem.equip[i].flag==1) break; - if(!(dbitem.equip[j].flag==1)){ - if(mapitem.equip[i].nameid==dbitem.equip[j].nameid){ - if ((mapitem.equip[i].equip==dbitem.equip[j].equip) && (mapitem.equip[i].identify==dbitem.equip[j].identify) && (mapitem.equip[i].amount==dbitem.equip[j].amount) && - - (mapitem.equip[i].refine==dbitem.equip[j].refine) && (mapitem.equip[i].attribute==dbitem.equip[j].attribute) && (mapitem.equip[i].card[0]==dbitem.equip[j].card[0]) && - (mapitem.equip[i].card[1]==dbitem.equip[j].card[1]) && (mapitem.equip[i].card[2]==dbitem.equip[j].card[2]) && (mapitem.equip[i].card[3]==dbitem.equip[j].card[3])) { - mapitem.equip[i].flag = 1; - dbitem.equip[j].flag = 1; - //printf("the same item : %d , equip : %d , i : %d , flag : %d\n", mapitem.equip[i].nameid,mapitem.equip[i].equip , i, mapitem.equip[i].flag); //DEBUG-STRING - } else { + while ((sql_row = mysql_fetch_row(sql_res))) { + flag = 0; + id = atoi(sql_row[0]); + for(i = 0; i < count; i++) { + if(mapitem[i].flag == 1) + continue; + if(mapitem[i].nameid == atoi(sql_row[1])) { // produced items fixup + if((mapitem[i].equip == atoi(sql_row[3])) && + (mapitem[i].identify == atoi(sql_row[4])) && + (mapitem[i].amount == atoi(sql_row[2])) && + (mapitem[i].refine == atoi(sql_row[5])) && + (mapitem[i].attribute == atoi(sql_row[6])) && + (mapitem[i].card[0] == atoi(sql_row[7])) && + (mapitem[i].card[1] == atoi(sql_row[8])) && + (mapitem[i].card[2] == atoi(sql_row[9])) && + (mapitem[i].card[3] == atoi(sql_row[10]))) { + //printf("the same item : %d , equip : %d , i : %d , flag : %d\n", mapitem.equip[i].nameid,mapitem.equip[i].equip , i, mapitem.equip[i].flag); //DEBUG-STRING + } else { +//==============================================Memory data > SQL =============================== + if(itemdb_isequip(mapitem[i].nameid) || (mapitem[i].card[0] == atoi(sql_row[7]))) { sprintf(tmp_sql,"UPDATE `%s` SET `equip`='%d', `identify`='%d', `refine`='%d'," - "`attribute`='%d', `card0`='%d', `card1`='%d', `card2`='%d', `card3`='%d', `amount`='%d' WHERE `id`='%d' LIMIT 1", - tablename, mapitem.equip[i].equip, mapitem.equip[i].identify, mapitem.equip[i].refine,mapitem.equip[i].attribute, mapitem.equip[i].card[0], - mapitem.equip[i].card[1], mapitem.equip[i].card[2], mapitem.equip[i].card[3], mapitem.equip[i].amount, dbitem.equip[j].id); - //printf("%s\n",tmp_sql); + "`attribute`='%d', `card0`='%d', `card1`='%d', `card2`='%d', `card3`='%d', `amount`='%d' WHERE `id`='%d' LIMIT 1", + tablename, mapitem[i].equip, mapitem[i].identify, mapitem[i].refine, mapitem[i].attribute, mapitem[i].card[0], + mapitem[i].card[1], mapitem[i].card[2], mapitem[i].card[3], mapitem[i].amount, id); if(mysql_query(&mysql_handle, tmp_sql)) printf("DB server Error (UPdate `equ %s`)- %s\n", tablename, mysql_error(&mysql_handle)); - mapitem.equip[i].flag=1; - dbitem.equip[j].flag=1; - //printf("not the same item : %d ; i : %d ; flag : %d\n", mapitem.equip[i].nameid, i, mapitem.equip[i].flag); } + //printf("not the same item : %d ; i : %d ; flag : %d\n", mapitem.equip[i].nameid, i, mapitem.equip[i].flag); } + flag = mapitem[i].flag = 1; + break; } } - } - - //printf("dbeqcount = %d\n",dbeqcount); - - for(i=1;i<dbeqcount;i++){ - //printf("dbitem.equip[i].flag = %d , dbitem.equip[i].id = %d\n",dbitem.equip[i].flag,dbitem.equip[i].id); - if (!(dbitem.equip[i].flag == 1)) { - sprintf(tmp_sql,"DELETE from `%s` where `id`='%d'",tablename , dbitem.equip[i].id); - //printf("%s", tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql)) - printf("DB server Error (DELETE `equ %s`)- %s\n", tablename ,mysql_error(&mysql_handle)); + if(!flag) { + sprintf(tmp_sql,"DELETE from `%s` where `id`='%d'", tablename, id); + if(mysql_query(&mysql_handle, tmp_sql)) + printf("DB server Error (DELETE `equ %s`)- %s\n", tablename, mysql_error(&mysql_handle)); } } - for(i=1;i<eqcount;i++){ - if(!(mapitem.equip[i].flag==1)){ - sprintf(tmp_sql,"INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`)" - " VALUES ( '%d','%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - tablename, selectoption, char_id, mapitem.equip[i].nameid, mapitem.equip[i].amount, mapitem.equip[i].equip, mapitem.equip[i].identify, mapitem.equip[i].refine, - mapitem.equip[i].attribute, mapitem.equip[i].card[0], mapitem.equip[i].card[1], mapitem.equip[i].card[2], mapitem.equip[i].card[3]); - //printf("%s", tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql)) - printf("DB server Error (INSERT `equ %s`)- %s\n",tablename ,mysql_error(&mysql_handle)); - } - } - - //======================================DEBUG================================================= - -// gettimeofday(&tv,NULL); -// strftime(tmpstr,24,"%Y-%m-%d %H:%M:%S",localtime(&(tv.tv_sec))); -// printf("\n\n"); -// printf("Working Table Name : EQU %s, Count : map %3d | db %3d \n",tablename ,eqcount ,dbeqcount); -// printf("*********************************************************************************\n"); -// printf("======================================MAP===================Char ID %10d===\n",char_id); -// printf("==flag ===name ===equip===ident===amoun===attri===card0===card1===card2===card3==\n"); -// for(j=1;j<eqcount;j++) -// printf("| %5d | %5d | %5d | %5d | %5d | %5d | %5d | %5d | %5d | %5d |\n", mapitem.equip[j].flag,mapitem.equip[j].nameid, mapitem.equip[j].equip, mapitem.equip[j].identify, mapitem.equip[j].refine,mapitem.equip[j].attribute, mapitem.equip[j].card[0], mapitem.equip[j].card[1], mapitem.equip[j].card[2], mapitem.equip[j].card[3]); -// printf("======================================DB=========================================\n"); -// printf("==flag ===name ===equip===ident===refin===attri===card0===card1===card2===card3==\n"); -// for(j=1;j<dbeqcount;j++) -// printf("| %5d | %5d | %5d | %5d | %5d | %5d | %5d | %5d | %5d | %5d |\n", dbitem.equip[j].flag ,dbitem.equip[j].nameid, dbitem.equip[j].equip, dbitem.equip[j].identify, dbitem.equip[j].amount,dbitem.equip[j].attribute, dbitem.equip[j].card[0], dbitem.equip[j].card[1], dbitem.equip[j].card[2], dbitem.equip[j].card[3]); -// printf("=================================================================================\n"); -// printf("=================================================Data Time %s===\n", tmpstr); -// printf("=================================================================================\n"); - + mysql_free_result(sql_res); } - //======================================DEBUG================================================== - - //=============================Not Equip ITEM========================================== - if((noteqcount==1) && (dbnoteqcount==1)){ - //printf("%s Not Equip Empty\n",tablename); - //item empty - } else { - - for(i=1;i<noteqcount;i++){ - for(j=1;j<dbnoteqcount;j++){ - if(mapitem.notequip[i].flag==1) break; - if(!(dbitem.notequip[j].flag==1)){ - if(mapitem.notequip[i].nameid==dbitem.notequip[j].nameid){ - if ((mapitem.notequip[i].amount==dbitem.notequip[j].amount) && (mapitem.notequip[i].equip==dbitem.notequip[j].equip) && (mapitem.notequip[i].identify==dbitem.notequip[j].identify) - && (mapitem.notequip[i].attribute==dbitem.notequip[j].attribute)) - { mapitem.notequip[i].flag=1; - dbitem.notequip[j].flag=1; - //printf("the same item : %d ; i : %d ; flag : %d\n", mapitem.notequip[i].nameid, i, mapitem.notequip[i].flag); //DEBUG-STRING - } - else{ - sprintf(tmp_sql,"UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d'," - "`attribute`='%d' WHERE `%s`='%d' AND `nameid`='%d'", - tablename, mapitem.notequip[i].amount, mapitem.notequip[i].equip, mapitem.notequip[i].identify, mapitem.notequip[i].attribute, - selectoption, char_id, mapitem.notequip[i].nameid); - //printf("%s",tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql)) - printf("DB server Error (UPdate `notequ %s`)- %s\n",tablename ,mysql_error(&mysql_handle)); - - mapitem.notequip[i].flag=1; - dbitem.notequip[j].flag=1; - } - } - } - } - } - - //printf("dbnoteqcount = %d\n",dbnoteqcount); - - for(i=1;i<dbnoteqcount;i++){ - //printf("dbitem.notequip[i].flag = %d , dbitem.notequip[i].id = %d\n",dbitem.notequip[i].flag,dbitem.notequip[i].id); - if(!(dbitem.notequip[i].flag==1)){ - sprintf(tmp_sql,"DELETE from `%s` where `id`='%d'", tablename, dbitem.notequip[i].id); - //printf("%s", tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql)) - printf("DB server Error (DELETE `notequ %s`)- %s\n", tablename ,mysql_error(&mysql_handle)); - } - } - for(i=1;i<noteqcount;i++){ - if(!(mapitem.notequip[i].flag==1)){ - sprintf(tmp_sql,"INSERT INTO `%s`( `%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`)" - " VALUES ('%d','%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - tablename ,selectoption , char_id, mapitem.notequip[i].nameid, mapitem.notequip[i].amount, mapitem.notequip[i].equip, mapitem.notequip[i].identify, mapitem.notequip[i].refine, - mapitem.notequip[i].attribute, mapitem.notequip[i].card[0], mapitem.notequip[i].card[1], mapitem.notequip[i].card[2], mapitem.notequip[i].card[3]); - //printf("%s", tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql)) - printf("DB server Error (INSERT `notequ %s`)- %s\n", tablename, mysql_error(&mysql_handle)); - } + for(i = 0; i < count; i++) { + if(!mapitem[i].flag) { + sprintf(tmp_sql,"INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3` )" + " VALUES ( '%d','%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d' )", + tablename, selectoption, char_id, mapitem[i].nameid, mapitem[i].amount, mapitem[i].equip, mapitem[i].identify, mapitem[i].refine, + mapitem[i].attribute, mapitem[i].card[0], mapitem[i].card[1], mapitem[i].card[2], mapitem[i].card[3]); + if(mysql_query(&mysql_handle, tmp_sql)) + printf("DB server Error (INSERT `equ %s`)- %s\n", tablename, mysql_error(&mysql_handle)); } + } //======================================DEBUG================================================= @@ -747,21 +731,23 @@ int memitemdata_to_sql(struct itemtemp mapitem, int eqcount, int noteqcount, int // printf("=================================================Data Time %s===\n", tmpstr); // printf("=================================================================================\n"); // - } + return 0; } - //===================================================================================================== int mmo_char_fromsql(int char_id, struct mmo_charstatus *p, int online){ - int i=0, n=0; + int i, n; + char *tmp_p = tmp_sql; + struct mmo_charstatus *cp; + + cp = (struct mmo_charstatus*)numdb_search(char_db_,char_id); + if (cp != NULL) + aFree(cp); memset(p, 0, sizeof(struct mmo_charstatus)); p->char_id = char_id; - - #ifdef DEBUG - printf("Loading Char [%d]... ",char_id); - #endif + printf("Loaded: "); //`char`( `char_id`,`account_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`, //9 //`str`,`agi`,`vit`,`int`,`dex`,`luk`, //15 //`max_hp`,`hp`,`max_sp`,`sp`,`status_point`,`skill_point`, //21 @@ -770,15 +756,23 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus *p, int online){ //`last_map`,`last_x`,`last_y`,`save_map`,`save_x`,`save_y`) //splite 2 parts. cause veeeery long SQL syntax - sprintf(tmp_sql, "SELECT * FROM `%s` WHERE `char_id` = '%d'",char_db, char_id); + sprintf(tmp_sql, "SELECT `char_id`,`account_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`," + "`str`,`agi`,`vit`,`int`,`dex`,`luk`, `max_hp`,`hp`,`max_sp`,`sp`,`status_point`,`skill_point` FROM `%s` WHERE `char_id` = '%d'",char_db, char_id); // TBR - sql_query(tmp_sql,"mmo_char_fromsql"); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `char`)- %s\n", mysql_error(&mysql_handle)); + } + + sql_res = mysql_store_result(&mysql_handle); - if ((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) { + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); + + p->char_id = char_id; p->account_id = atoi(sql_row[1]); p->char_num = atoi(sql_row[2]); strcpy(p->name, sql_row[3]); - p->class = atoi(sql_row[4]); + p->class_ = atoi(sql_row[4]); p->base_level = atoi(sql_row[5]); p->job_level = atoi(sql_row[6]); p->base_exp = atoi(sql_row[7]); @@ -796,43 +790,57 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus *p, int online){ p->sp = atoi(sql_row[19]); p->status_point = atoi(sql_row[20]); p->skill_point = atoi(sql_row[21]); - p->option = atoi(sql_row[22]); - p->karma = atoi(sql_row[23]); - p->manner = atoi(sql_row[24]); - p->party_id = atoi(sql_row[25]); - p->guild_id = atoi(sql_row[26]); - p->pet_id = atoi(sql_row[27]); - p->hair = atoi(sql_row[28]); - p->hair_color = atoi(sql_row[29]); - p->clothes_color = atoi(sql_row[30]); - p->weapon = atoi(sql_row[31]); - p->shield = atoi(sql_row[32]); - p->head_top = atoi(sql_row[33]); - p->head_mid = atoi(sql_row[34]); - p->head_bottom = atoi(sql_row[35]); - strcpy(p->last_point.map,sql_row[36]); - p->last_point.x = atoi(sql_row[37]); - p->last_point.y = atoi(sql_row[38]); - strcpy(p->save_point.map,sql_row[39]); - p->save_point.x = atoi(sql_row[40]); - p->save_point.y = atoi(sql_row[41]); - p->partner_id = atoi(sql_row[42]); + //free mysql result. + mysql_free_result(sql_res); + } else + printf("char1 - failed\n"); //Error?! ERRRRRR WHAT THAT SAY!? + printf("(\033[1;32m%d\033[0m)\033[1;32m%s\033[0m\t[",p->char_id,p->name); + printf("char1 "); + + sprintf(tmp_sql, "SELECT `option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`hair`,`hair_color`," + "`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`," + "`last_map`,`last_x`,`last_y`,`save_map`,`save_x`,`save_y`, `partner_id`, `father`, `mother`, `child` FROM `%s` WHERE `char_id` = '%d'",char_db, char_id); // TBR + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `char2`)- %s\n", mysql_error(&mysql_handle)); + } + + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); + + + p->option = atoi(sql_row[0]); p->karma = atoi(sql_row[1]); p->manner = atoi(sql_row[2]); + p->party_id = atoi(sql_row[3]); p->guild_id = atoi(sql_row[4]); p->pet_id = atoi(sql_row[5]); + + p->hair = atoi(sql_row[6]); p->hair_color = atoi(sql_row[7]); p->clothes_color = atoi(sql_row[8]); + p->weapon = atoi(sql_row[9]); p->shield = atoi(sql_row[10]); + p->head_top = atoi(sql_row[11]); p->head_mid = atoi(sql_row[12]); p->head_bottom = atoi(sql_row[13]); + strcpy(p->last_point.map,sql_row[14]); p->last_point.x = atoi(sql_row[15]); p->last_point.y = atoi(sql_row[16]); + strcpy(p->save_point.map,sql_row[17]); p->save_point.x = atoi(sql_row[18]); p->save_point.y = atoi(sql_row[19]); + p->partner_id = atoi(sql_row[20]); p->father = atoi(sql_row[21]); p->mother = atoi(sql_row[22]); p->child = atoi(sql_row[23]); //free mysql result. mysql_free_result(sql_res); -#ifdef DEBUG - printf("Loading of char [%d] Completed!\n",char_id); - } else { - printf("Loading of char [%d] FAILED!\n",char_id); //Error?! ERRRRRR WHAT THAT SAY!? -#endif - } + } else + printf("char2 - failed\n"); //Error?! ERRRRRR WHAT THAT SAY!? + + if (p->last_point.x == 0 || p->last_point.y == 0 || p->last_point.map[0] == '\0') + memcpy(&p->last_point, &start_point, sizeof(start_point)); + + if (p->save_point.x == 0 || p->save_point.y == 0 || p->save_point.map[0] == '\0') + memcpy(&p->save_point, &start_point, sizeof(start_point)); + + printf("char2 "); //read memo data //`memo` (`memo_id`,`char_id`,`map`,`x`,`y`) - sprintf(tmp_sql, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`='%d'",memo_db, char_id); - sql_query(tmp_sql,"mmo_char_fromsql"); + sprintf(tmp_sql, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`='%d'",memo_db, char_id); // TBR + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `memo`)- %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); - if ((sql_res = mysql_store_result(&mysql_handle))) { + if (sql_res) { for(i=0;(sql_row = mysql_fetch_row(sql_res));i++){ strcpy (p->memo_point[i].map,sql_row[0]); p->memo_point[i].x=atoi(sql_row[1]); @@ -841,83 +849,87 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus *p, int online){ } mysql_free_result(sql_res); } -#ifdef DEBUG - printf("Char [%s] - Memo Loaded\n",p->name); -#endif + printf("memo "); //read inventory //`inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`) - sprintf(tmp_sql, "SELECT * FROM `%s` WHERE `char_id`='%d'",inventory_db, char_id); - sql_query(tmp_sql,"mmo_char_fromsql"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { + sprintf(tmp_sql, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`" + "FROM `%s` WHERE `char_id`='%d'",inventory_db, char_id); // TBR + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `inventory`)- %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { for(i=0;(sql_row = mysql_fetch_row(sql_res));i++){ - p->inventory[i].id = atoi(sql_row[1]); - p->inventory[i].nameid = atoi(sql_row[2]); - p->inventory[i].amount = atoi(sql_row[3]); - p->inventory[i].equip = atoi(sql_row[4]); - p->inventory[i].identify = atoi(sql_row[5]); - p->inventory[i].refine = atoi(sql_row[6]); - p->inventory[i].attribute = atoi(sql_row[7]); - p->inventory[i].card[0] = atoi(sql_row[8]); - p->inventory[i].card[1] = atoi(sql_row[9]); - p->inventory[i].card[2] = atoi(sql_row[10]); - p->inventory[i].card[3] = atoi(sql_row[11]); + p->inventory[i].id = atoi(sql_row[0]); + p->inventory[i].nameid = atoi(sql_row[1]); + p->inventory[i].amount = atoi(sql_row[2]); + p->inventory[i].equip = atoi(sql_row[3]); + p->inventory[i].identify = atoi(sql_row[4]); + p->inventory[i].refine = atoi(sql_row[5]); + p->inventory[i].attribute = atoi(sql_row[6]); + p->inventory[i].card[0] = atoi(sql_row[7]); + p->inventory[i].card[1] = atoi(sql_row[8]); + p->inventory[i].card[2] = atoi(sql_row[9]); + p->inventory[i].card[3] = atoi(sql_row[10]); } mysql_free_result(sql_res); } -#ifdef DEBUG - printf("Char [%s] - Inventory Loaded\n",p->name); -#endif + printf("inventory "); + //read cart. //`cart_inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`) - sprintf(tmp_sql, "SELECT * FROM `%s` WHERE `char_id`='%d'",cart_db, char_id); - sql_query(tmp_sql,"mmo_char_fromsql"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { + sprintf(tmp_sql, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`" + "FROM `%s` WHERE `char_id`='%d'",cart_db, char_id); // TBR + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `cart_inventory`)- %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { for(i=0;(sql_row = mysql_fetch_row(sql_res));i++){ - p->cart[i].id = atoi(sql_row[1]); - p->cart[i].nameid = atoi(sql_row[2]); - p->cart[i].amount = atoi(sql_row[3]); - p->cart[i].equip = atoi(sql_row[4]); - p->cart[i].identify = atoi(sql_row[5]); - p->cart[i].refine = atoi(sql_row[6]); - p->cart[i].attribute = atoi(sql_row[7]); - p->cart[i].card[0] = atoi(sql_row[8]); - p->cart[i].card[1] = atoi(sql_row[9]); - p->cart[i].card[2] = atoi(sql_row[10]); - p->cart[i].card[3] = atoi(sql_row[11]); + p->cart[i].id = atoi(sql_row[0]); + p->cart[i].nameid = atoi(sql_row[1]); + p->cart[i].amount = atoi(sql_row[2]); + p->cart[i].equip = atoi(sql_row[3]); + p->cart[i].identify = atoi(sql_row[4]); + p->cart[i].refine = atoi(sql_row[5]); + p->cart[i].attribute = atoi(sql_row[6]); + p->cart[i].card[0] = atoi(sql_row[7]); + p->cart[i].card[1] = atoi(sql_row[8]); + p->cart[i].card[2] = atoi(sql_row[9]); + p->cart[i].card[3] = atoi(sql_row[10]); } mysql_free_result(sql_res); } -#ifdef DEBUG - printf("Char [%s] - Cart Inventory Loaded\n",p->name); -#endif + printf("cart "); //read skill //`skill` (`char_id`, `id`, `lv`) - sprintf(tmp_sql, "SELECT `id`, `lv` FROM `%s` WHERE `char_id`='%d'",skill_db, char_id); - sql_query(tmp_sql,"mmo_char_fromsql"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { + sprintf(tmp_sql, "SELECT `id`, `lv` FROM `%s` WHERE `char_id`='%d'",skill_db, char_id); // TBR + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `skill`)- %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { for(i=0;(sql_row = mysql_fetch_row(sql_res));i++){ - n = atoi(sql_row[0]); - p->skill[n].id = n; + n = atoi(sql_row[0]); + p->skill[n].id = n; //memory!? shit!. p->skill[n].lv = atoi(sql_row[1]); } mysql_free_result(sql_res); } -#ifdef DEBUG - printf("Char [%s] - Skills Loaded\n",p->name); -#endif + printf("skill "); //global_reg //`global_reg_value` (`char_id`, `str`, `value`) - sprintf(tmp_sql, "SELECT `str`, `value` FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, char_id); - sql_query(tmp_sql,"mmo_char_fromsql"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { + sprintf(tmp_sql, "SELECT `str`, `value` FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, char_id); // TBR + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `global_reg_value`)- %s\n", mysql_error(&mysql_handle)); + } + i = 0; + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { for(i=0;(sql_row = mysql_fetch_row(sql_res));i++){ strcpy (p->global_reg[i].str, sql_row[0]); p->global_reg[i].value = atoi (sql_row[1]); @@ -925,76 +937,152 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus *p, int online){ mysql_free_result(sql_res); } p->global_reg_num=i; -#ifdef DEBUG - printf("Char [%s] - Global Reg Loaded\n",p->name); -#endif + + //Friends List Load + + for(i=0;i<20;i++) { + p->friend_id[i] = 0; + p->friend_name[i][0] = '\0'; + } + + tmp_p += sprintf(tmp_p, "SELECT `id`, `account_id`"); + + for(i=0;i<20;i++) + tmp_p += sprintf(tmp_p, ", `friend_id%d`, `name%d`", i, i); + + tmp_p += sprintf(tmp_p, " FROM `%s` WHERE `account_id`='%d' ", friend_db, char_id); // TBR + + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `friends list`)- %s\n", mysql_error(&mysql_handle)); + } + + sql_res = mysql_store_result(&mysql_handle); + sql_row = mysql_fetch_row(sql_res); + + i=mysql_num_rows(sql_res); + + // debugg + //printf("mysql: %d\n",i); + + // Create an entry for the character if it doesnt already have one + if(!i) { + + insert_friends(char_id); + + } else { + + if (sql_res) { + for(i=0;i<20;i++) { + p->friend_id[i] = atoi(sql_row[i*2 +2]); + sprintf(p->friend_name[i], "%s", sql_row[i*2 +3]); + } + mysql_free_result(sql_res); + } + } + + printf("friends "); + + //-- end friends list load -- if (online) { - sprintf(tmp_sql, "UPDATE `%s` SET `online`='%d' WHERE `char_id`='%d'",char_db,online,char_id); - sql_query(tmp_sql,"mmo_char_fromsql"); + set_char_online(char_id,p->account_id); } -#ifdef DEBUG - printf("Char [%d][%s] - Loading Complete\n",char_id,p->name); -#endif + printf("char data load success]\n"); //ok. all data load successfuly! + + cp = (struct mmo_charstatus *) aMalloc(sizeof(struct mmo_charstatus)); + memcpy(cp, p, sizeof(struct mmo_charstatus)); + numdb_insert(char_db_, char_id,cp); return 1; } //========================================================================================================== int mmo_char_sql_init(void) { - int i=0; - #ifdef DEBUG - int cid=0; - #endif + int charcount; + + char_db_=numdb_init(); + printf("init start.......\n"); // memory initialize // no need to set twice size in this routine. but some cause segmentation error. :P - #ifdef DEBUG - printf("Initializing char memory...(%d byte)\n",sizeof(struct mmo_charstatus)*2); - #endif - + printf("initializing char memory...(%d byte)\n",sizeof(struct mmo_charstatus)*2); CREATE(char_dat, struct mmo_charstatus, 2); + memset(char_dat, 0, sizeof(struct mmo_charstatus)*2); +/* Initialized in inter.c already [Wizputer] + // DB connection initialized + // for char-server session only + mysql_init(&mysql_handle); + printf("Connect DB server....(char server)\n"); + if(!mysql_real_connect(&mysql_handle, char_server_ip, char_server_id, char_server_pw, char_server_db ,char_server_port, (char *)NULL, 0)) { + // SQL connection pointer check + printf("%s\n",mysql_error(&mysql_handle)); + exit(1); + } else { + printf("connect success! (char server)\n"); + } +*/ /* Removed .. not needed now :P sprintf(tmp_sql , "SELECT count(*) FROM `%s`", char_db); - sql_query(tmp_sql,"mmo_char_sql_init"); - - if((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) { - i = atoi (sql_row[0]); - #ifdef DEBUG - printf("Total number of chars in DB [%d]\n",i); - #endif + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); } + sql_res = mysql_store_result(&mysql_handle) ; + sql_row = mysql_fetch_row(sql_res); + printf("total char data -> '%s'.......\n",sql_row[0]); + i = atoi (sql_row[0]); + mysql_free_result(sql_res); - mysql_free_result(sql_res); - - // Because it's no longer needed, I made it debug. Some people may still want to know the highest - // char_id. It has no functional purpose though. [Ajarn] - #ifdef DEBUG - if (i != 0) { + if (i !=0) { sprintf(tmp_sql , "SELECT max(`char_id`) FROM `%s`", char_db); - sql_query(tmp_sql,"mmo_char_sql_init"); - - if((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) - cid = atoi (sql_row[0]); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle) ; + sql_row = mysql_fetch_row(sql_res); + char_id_count = atoi (sql_row[0]); mysql_free_result(sql_res); - } - printf("Highest Char ID [%d]\n",cid); - #endif + } else + printf("set char_id_count: %d.......\n",char_id_count); + */ + sprintf(tmp_sql, "SELECT `char_id` FROM `%s`", char_db); + if(mysql_query(&mysql_handle, tmp_sql)){ + //fail :( + printf("SQL Error (in select the charid .. (all)): %s", mysql_error(&mysql_handle)); + }else{ + sql_res = mysql_store_result(&mysql_handle); + if(sql_res){ + charcount = mysql_num_rows(sql_res); + printf("total char data -> '%d'.......\n", charcount); + mysql_free_result(sql_res); + }else{ + printf("total char data -> '0'.......\n"); + } + } + + if(char_per_account == 0){ + printf("Chars per Account: 'Unlimited'.......\n"); + }else{ + printf("Chars per Account: '%d'.......\n", char_per_account); + } - if (i == 0) { - // If there is no characters in the SQL DB, make sure the starting id will be MIN_CHAR_ID - // Remove once main.sql has this to begin with and it's a standard to have it be this way - // (thus saving a check) [Ajarn] - sprintf(tmp_sql , "ALTER TABLE `%s` AUTO_INCREMENT = %d", char_db, MIN_CHAR_ID-1); - sql_query(tmp_sql,"mmo_char_sql_init"); - } + //sprintf(tmp_sql , "REPLACE INTO `%s` SET `online`=0", char_db); //OLD QUERY ! BUGGED + sprintf(tmp_sql, "UPDATE `%s` SET `online` = '0'", char_db);//fixed the on start 0 entrys! + if (mysql_query(&mysql_handle, tmp_sql)) + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + //sprintf(tmp_sql , "REPLACE INTO `%s` SET `online`=0", guild_member_db); //OLD QUERY ! BUGGED + sprintf(tmp_sql, "UPDATE `%s` SET `online` = '0'", guild_member_db);//fixed the 0 entrys in start .. + if (mysql_query(&mysql_handle, tmp_sql)) + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); - #ifdef DEBUG - printf("Init finsihed\n"); - #endif + //sprintf(tmp_sql , "REPLACE INTO `%s` SET `connect_member`=0", guild_db); //OLD QUERY BUGGED! + sprintf(tmp_sql, "UPDATE `%s` SET `connect_member` = '0'", guild_db);//fixed the 0 entrys in start..... + if (mysql_query(&mysql_handle, tmp_sql)) + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + + printf("init end.......\n"); return 0; } @@ -1004,105 +1092,246 @@ int mmo_char_sql_init(void) { int make_new_char_sql(int fd, unsigned char *dat) { struct char_session_data *sd; char t_name[100]; - int i, cid; - - //aphostropy error check! - fixed! - jstrescapecpy(t_name, dat); - - #ifdef DEBUG - printf("Making new char [%s]\n",dat); - #endif + int i, char_id, temp; - sd = session[fd]->session_data; + //aphostropy error check! - fixed! + jstrescapecpy(t_name, (char*)dat); + + sd = (struct char_session_data*)session[fd]->session_data; + + printf("[CHAR] Add - "); + + //check for charcount (maxchars) :) + if(char_per_account != 0){ + sprintf(tmp_sql, "SELECT `account_id` FROM `%s` WHERE `account_id` = '%d'", char_db, sd->account_id); + if(mysql_query(&mysql_handle, tmp_sql)){ + printf("fail, SQL Error: %s !!FAIL!!\n", tmp_sql); + } + sql_res = mysql_store_result(&mysql_handle); + if(sql_res){ + //ok + temp = mysql_num_rows(sql_res); + if(temp >= char_per_account){ + //hehe .. limit exceeded :P + printf("fail (aid: %d), charlimit exceeded.\n", sd->account_id); + mysql_free_result(sql_res); + return -2; + } + mysql_free_result(sql_res); + } + } + // Check Authorised letters/symbols in the name of the character if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised - for (i = 0; i < strlen(dat); i++) + for (i = 0; i < strlen((const char*)dat); i++) if (strchr(char_name_letters, dat[i]) == NULL) - return -1; + return -2; } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden - for (i = 0; i < strlen(dat); i++) + for (i = 0; i < strlen((const char*)dat); i++) if (strchr(char_name_letters, dat[i]) != NULL) - return -1; + return -2; } // else, all letters/symbols are authorised (except control char removed before) + //check stat error if ((dat[24]+dat[25]+dat[26]+dat[27]+dat[28]+dat[29]!=5*6 ) || - (dat[30] >= 9) || (dat[33] <= 0) || (dat[33] >= 20) || + (dat[30] >= 9) || + (dat[33] <= 0) || (dat[33] >= 20) || (dat[31] >= 9)) { // check individual stat value for(i = 24; i <= 29; i++) { if (dat[i] < 1 || dat[i] > 9) { - return -1; + printf("fail (aid: %d), stats error(bot cheat?!)\n", sd->account_id); + return -2; } } + if (log_char) { + // char.log to charlog + sprintf(tmp_sql,"INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" + "VALUES (NOW(), '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", + charlog_db,"make new char error", sd->account_id, dat[30], dat, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); + //query + mysql_query(&mysql_handle, tmp_sql); + } + //printf("make new char error %d-%d %s %d, %d, %d, %d, %d, %d %d, %d" RETCODE, + // fd, dat[30], dat, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); + + printf("fail (aid: %d), stats error(bot cheat?!)\n", sd->account_id); + return -2; + } + + if (log_char) { // char.log to charlog - sprintf(tmp_sql,"INSERT DELAYED INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" + sprintf(tmp_sql,"INSERT INTO `%s`(`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" "VALUES (NOW(), '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - charlog_db,"make new char error", sd->account_id, dat[30], dat, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); + charlog_db,"make new char", sd->account_id, dat[30], dat, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); //query - sql_query(tmp_sql,"amke_new_char_sql"); - - #ifdef DEBUG - printf("Make new char error %d-%d %s %d, %d, %d, %d, %d, %d %d, %d" RETCODE, - fd, dat[30], dat, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); - #endif + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("fail(log error), SQL error: %s\n", mysql_error(&mysql_handle)); + } + } + //printf("make new char %d-%d %s %d, %d, %d, %d, %d, %d - %d, %d" RETCODE, + // fd, dat[30], dat, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); + //Check Name (already in use?) + sprintf(tmp_sql, "SELECT `name` FROM `%s` WHERE `name` = '%s'",char_db, t_name); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("fail (namecheck!), SQL error: %s\n", mysql_error(&mysql_handle)); + return -2; + } + sql_res = mysql_store_result(&mysql_handle); + if(sql_res){ + temp = mysql_num_rows(sql_res); + + if (temp > 0) { + mysql_free_result(sql_res); + printf("fail, charname already in use\n"); return -1; + } + mysql_free_result(sql_res); } - // char.log to charlog - sprintf(tmp_sql,"INSERT DELAYED INTO `%s`(`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" - "VALUES (NOW(), '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - charlog_db,"make new char", sd->account_id, dat[30], dat, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); - //query - sql_query(tmp_sql,"make_new_char_sql"); - - #ifdef DEBUG - printf("make new char %d-%d %s %d, %d, %d, %d, %d, %d - %d, %d" RETCODE, - fd, dat[30], dat, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); - #endif - // check char slot. - sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d'",char_db, sd->account_id, dat[30]); - sql_query(tmp_sql,"make_new_char_sql"); - - if((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) { - if (atoi(sql_row[0]) > 0) { - mysql_free_result(sql_res); - return -1; - } else - mysql_free_result(sql_res); + sprintf(tmp_sql, "SELECT `account_id`, `char_num` FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d'",char_db, sd->account_id, dat[30]); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("fail (charslot check), SQL error: %s\n", mysql_error(&mysql_handle)); } + sql_res = mysql_store_result(&mysql_handle); + + if(sql_res){ + temp = mysql_num_rows(sql_res); + if (temp > 0) { + mysql_free_result(sql_res); + printf("fail (aid: %d, slot: %d), slot already in use\n", sd->account_id, dat[30]); + return -2; + } + mysql_free_result(sql_res); + } + //char_id_count++; - // make new char. - sprintf(tmp_sql,"INSERT INTO `%s` (`account_id`,`char_num`,`name`,`zeny`,`str`,`agi`,`vit`,`int`,`dex`,`luk`," - "`max_hp`,`hp`,`max_sp`,`sp`,`hair`,`hair_color`,`last_map`,`last_x`,`last_y`,`save_map`,`save_x`,`save_y`)" - " VALUES ('%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d','%s','%d','%d','%s','%d','%d')", - char_db, sd->account_id , dat[30] , t_name, start_zeny, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], - (40 * (100 + dat[26])/100) , (40 * (100 + dat[26])/100 ), (11 * (100 + dat[27])/100), (11 * (100 + dat[27])/100), dat[33], dat[31], - start_point.map,start_point.x,start_point.y, start_point.map,start_point.x,start_point.y); + // make new char. + /* + sprintf(tmp_sql,"INSERT INTO `%s` (`char_id`,`account_id`,`char_num`,`name`,`zeny`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`,`hair`,`hair_color`)" + " VALUES ('%d', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d')", + char_db, char_id_count, sd->account_id , dat[30] , t_name, start_zeny, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], + (40 * (100 + dat[26])/100) , (40 * (100 + dat[26])/100 ), (11 * (100 + dat[27])/100), (11 * (100 + dat[27])/100), dat[33], dat[31]); if (mysql_query(&mysql_handle, tmp_sql)) { - printf("DB server Error (insert new char into `char`)- %s\n", mysql_error(&mysql_handle)); - return -1; + printf("DB server Error (insert `char`)- %s\n", mysql_error(&mysql_handle)); } - cid = mysql_last_insert_id(sql_res); - //`inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`) - sprintf(tmp_sql,"INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d'),('%d', '%d', '%d', '%d', '%d')", - inventory_db, cid, 1201,1,0x02,1,cid,2301,1,0x10,1); //add Knife and Cotton Shirt - sql_query(tmp_sql,"make_new_char_sql"); + sprintf(tmp_sql,"INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", + inventory_db, char_id_count, 1201,1,0x02,1); //add Knife + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (insert `inventory`)- %s\n", mysql_error(&mysql_handle)); + } + + sprintf(tmp_sql,"INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", + inventory_db, char_id_count, 2301,1,0x10,1); //add Cotton Shirt + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (insert `inventory`)- %s\n", mysql_error(&mysql_handle)); + } + // respawn map and start point set + sprintf(tmp_sql,"UPDATE `%s` SET `last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d' WHERE `char_id` = '%d'", + char_db, start_point.map,start_point.x,start_point.y, start_point.map,start_point.x,start_point.y, char_id_count); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle)); + } + + + // Insert friends list + insert_friends(char_id_count); + */ + + //New Querys [Sirius] + //Insert the char to the 'chardb' ^^ + sprintf(tmp_sql, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`, `max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES ('%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')", char_db, sd->account_id , dat[30] , t_name, start_zeny, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], (40 * (100 + dat[26])/100) , (40 * (100 + dat[26])/100 ), (11 * (100 + dat[27])/100), (11 * (100 + dat[27])/100), dat[33], dat[31], start_point.map, start_point.x, start_point.y, start_point.map, start_point.x, start_point.y); + if(mysql_query(&mysql_handle, tmp_sql)){ + printf("failed (insert in chardb), SQL error: %s\n", mysql_error(&mysql_handle)); + return -2; //No, stop the procedure! + } + + //Now we need the charid from sql! + sprintf(tmp_sql, "SELECT `char_id` FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' AND `name` = '%s'", char_db, sd->account_id , dat[30] , t_name); + if(mysql_query(&mysql_handle, tmp_sql)){ + printf("failed (get char_id), SQL error: %s\n", mysql_error(&mysql_handle)); + //delete the char ..(no trash in DB!) + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' AND `name` = '%s'", char_db, sd->account_id, dat[30], t_name); + mysql_query(&mysql_handle, tmp_sql); + return -2; //XD end of the (World? :P) .. charcreate (denied) + }else{ + //query ok -> get the data! + sql_res = mysql_store_result(&mysql_handle); + if(sql_res){ + sql_row = mysql_fetch_row(sql_res); + char_id = atoi(sql_row[0]); //char id :) + mysql_free_result(sql_res); + if(char_id <= 0){ + printf("failed (get char id..) CHARID wrong!\n"); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' AND `name` = '%s'", char_db, sd->account_id, dat[30], t_name); + mysql_query(&mysql_handle, tmp_sql); + return -2; //charcreate denied .. + } + }else{ + //prevent to crash (if its false, and we want to free -> segfault :) + printf("failed (get char id.. res), SQL error: %s\n", mysql_error(&mysql_handle)); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' AND `name` = '%s'", char_db, sd->account_id, dat[30], t_name); + mysql_query(&mysql_handle, tmp_sql); + return -2; //end ...... -> charcreate failed :) + } + } + + //Give the char the default items + //knife + sprintf(tmp_sql,"INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", inventory_db, char_id, 1201,1,0x02,1); //add Knife + if (mysql_query(&mysql_handle, tmp_sql)){ + printf("fail (insert in inventory the 'knife'), SQL error: %s\n", mysql_error(&mysql_handle)); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' AND `name` = '%s'", char_db, sd->account_id, dat[30], t_name); + mysql_query(&mysql_handle, tmp_sql); + return -2;//end XD + } + //cotton shirt + sprintf(tmp_sql,"INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", inventory_db, char_id, 2301,1,0x10,1); //add Cotton Shirt + if (mysql_query(&mysql_handle, tmp_sql)){ + printf("fail (insert in inventroxy the 'cotton shirt'), SQL error: %s\n", mysql_error(&mysql_handle)); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' AND `name` = '%s'", char_db, sd->account_id, dat[30], t_name); + mysql_query(&mysql_handle, tmp_sql); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `char_id` = '%d'", inventory_db, char_id); + mysql_query(&mysql_handle, tmp_sql); + return -2; //end.... + } + + if(!insert_friends(char_id)){ + printf("fail (friendlist entrys..)\n"); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `char_id` = '%d'", char_db, char_id); + mysql_query(&mysql_handle, tmp_sql); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `char_id` = '%d'", inventory_db, char_id); + mysql_query(&mysql_handle, tmp_sql); + return -2; //end.. charcreate failed + } + + //printf("making new char success - id:(\033[1;32m%d\033[0m\tname:\033[1;32%s\033[0m\n", char_id, t_name); + printf("success, aid: %d, cid: %d, slot: %d, name: %s\n", sd->account_id, char_id, dat[30], t_name); + return char_id; +} + +//========================================================================================================== + +void mmo_char_sync(void){ + printf("mmo_char_sync() - nothing to do\n"); +} - #ifdef DEBUG - printf("Make new char success - id:(\033[1;32m%d\033[0m\tname:\033[1;32%s\033[0m\n", cid, t_name); - #endif +// to do +/////////////////////////// - return cid; +int mmo_char_sync_timer(int tid, unsigned int tick, int id, int data) { + printf("mmo_char_sync_timer() tic - no works to do\n"); + return 0; } int count_users(void) { @@ -1110,7 +1339,7 @@ int count_users(void) { if (login_fd > 0 && session[login_fd]){ users = 0; - for(i = 0; i < MAX_MAP_SERVERS && i < servers_connected; i++) { + for(i = 0; i < MAX_MAP_SERVERS; i++) { if (server_fd[i] >= 0) { users += server[i].users; } @@ -1120,52 +1349,40 @@ int count_users(void) { return 0; } -int send_users_tologin(int tid, unsigned int tick, int id, int data) { - int users = count_users(); - char buf[16]; - - if (login_fd > 0 && session[login_fd]) { - // send number of user to login server - WFIFOW(login_fd,0) = 0x2714; - WFIFOL(login_fd,2) = users; - WFIFOSET(login_fd,6); - } - // send number of players to all map-servers - WBUFW(buf,0) = 0x2b00; - WBUFL(buf,2) = users; - mapif_sendall(buf, 6); - - return 0; -} - - - int mmo_char_send006b(int fd, struct char_session_data *sd) { int i, j, found_num = 0; struct mmo_charstatus *p = NULL; - +// hehe. commented other. anyway there's no need to use older version. +// if use older packet version just uncomment that! +//#ifdef NEW_006b const int offset = 24; +//#else +// int offset = 4; +//#endif - #ifdef DEBUG - printf("Send Chars (account:%d)\n",sd->account_id); - #endif + printf("mmo_char_send006b start.. (account:%d)\n",sd->account_id); +// printf("offset -> %d...\n",offset); + + set_char_online(99,sd->account_id); //search char. sprintf(tmp_sql, "SELECT `char_id` FROM `%s` WHERE `account_id` = '%d'",char_db, sd->account_id); - sql_query(tmp_sql,"mmo_char_send006b"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { found_num = mysql_num_rows(sql_res); - - #ifdef DEBUG printf("number of chars: %d\n", found_num); - #endif - - for(i=0;(sql_row = mysql_fetch_row(sql_res));i++) + i = 0; + while((sql_row = mysql_fetch_row(sql_res))) { sd->found_char[i] = atoi(sql_row[0]); + i++; + } + mysql_free_result(sql_res); } - mysql_free_result(sql_res); +// printf("char fetching end (total: %d)....\n", found_num); for(i = found_num; i < 9; i++) sd->found_char[i] = -1; @@ -1174,9 +1391,7 @@ int mmo_char_send006b(int fd, struct char_session_data *sd) { WFIFOW(fd, 0) = 0x6b; WFIFOW(fd, 2) = offset + found_num * 106; - #ifdef DEBUG printf("(\033[1;13m%d\033[0m) Request Char Data:\n",sd->account_id); - #endif for(i = 0; i < found_num; i++) { mmo_char_fromsql(sd->found_char[i], char_dat, 0); @@ -1204,9 +1419,15 @@ int mmo_char_send006b(int fd, struct char_session_data *sd) { WFIFOW(fd,j+46) = (p->sp > 0x7fff) ? 0x7fff : p->sp; WFIFOW(fd,j+48) = (p->max_sp > 0x7fff) ? 0x7fff : p->max_sp; WFIFOW(fd,j+50) = DEFAULT_WALK_SPEED; // p->speed; - WFIFOW(fd,j+52) = p->class; + WFIFOW(fd,j+52) = p->class_; WFIFOW(fd,j+54) = p->hair; - WFIFOW(fd,j+56) = p->weapon; + + // pecopeco knights/crusaders crash fix + if (p->class_ == 13 || p->class_ == 21 || + p->class_ == 4014 || p->class_ == 4022) + WFIFOW(fd,j+56) = 0; + else WFIFOW(fd,j+56) = p->weapon; + WFIFOW(fd,j+58) = p->base_level; WFIFOW(fd,j+60) = p->skill_point; WFIFOW(fd,j+62) = p->head_bottom; @@ -1228,246 +1449,22 @@ int mmo_char_send006b(int fd, struct char_session_data *sd) { } WFIFOSET(fd,WFIFOW(fd,2)); - - #ifdef DEBUG - printf("Sent [%d] Chars to [%d]\n",found_num,sd->account_id); - #endif - +// printf("mmo_char_send006b end..\n"); return 0; } -int reply_login_request(int fd, int len) { - if (len < 3) - return -1; - - if (RFIFOB(fd, 2)) { - printf("Can not connect to login-server.\n"); - printf("The server communication passwords (default s1/p1) is probably invalid.\n"); - printf("Also, please make sure your login db has the username/password present and the sex of the account is S.\n"); - printf("If you changed the communication passwords, change them back at map_athena.conf and char_athena.conf\n"); - return -1; - }else { - printf("Connected to login-server (connection #%d).\n", fd); - // if no map-server already connected, display a message... - if(!servers_connected) - printf("Awaiting maps from map-server.\n"); - - // send USER COUNT PING to login server. - #ifdef DEBUG - printf("Add timer: (send_users_tologin)\n"); - #endif - - user_count_timer = add_timer_interval(gettick() + 10, send_users_tologin, 0, 0, 5 * 1000); - } - - RFIFOSKIP(fd, 3); - - return 0; -} - -int send_chars(int fd, int len) { - if(len<51) - return -1; - - int i; - struct char_session_data *sd; - - for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data) && sd->account_id == RFIFOL(fd,2)) { - if (RFIFOB(fd,6) != 0) { - WFIFOW(i,0) = 0x6c; - WFIFOB(i,2) = 0x42; - WFIFOSET(i,3); - } else if (max_connect_user == 0 || count_users() < max_connect_user) { - sd->connect_until_time = (time_t)RFIFOL(fd,47); - // send characters to player - mmo_char_send006b(i, sd); - } else { - // refuse connection: too much online players - WFIFOW(i,0) = 0x6c; - WFIFOW(i,2) = 0; - WFIFOSET(i,3); - } - } - } - RFIFOSKIP(fd,51); - - return 0; -} - -int connect_until_reply(int fd, int len) { - if (len < 50) - return -1; - - int i; - struct char_session_data *sd; - - for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data)) { - if (sd->account_id == RFIFOL(fd,2)) { - sd->connect_until_time = (time_t)RFIFOL(fd,46); - break; - } - } - } - - RFIFOSKIP(fd,50); - - return 0; -} - -// changesex reply (modified by [Yor]) -int change_sex_reply(int fd, int len) { - if (len < 7) - return -1; - - int acc, sex, i; - unsigned char buf[16]; - struct char_session_data *sd; - - acc = RFIFOL(fd,2); - sex = RFIFOB(fd,6); - RFIFOSKIP(fd, 7); - - if (acc > 0) { - sprintf(tmp_sql, "SELECT `char_id`,`class`,`skill_point` FROM `%s` WHERE `account_id` = '%d'",char_db, acc); - sql_query(tmp_sql,"change_sex_reply"); - - if ((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) { - int char_id, jobclass, skill_point, char_class; - - char_id = atoi(sql_row[0]); - jobclass = atoi(sql_row[1]); - skill_point = atoi(sql_row[2]); - char_class = jobclass; - - if (jobclass == 19 || jobclass == 20 || - jobclass == 4020 || jobclass == 4021 || - jobclass == 4042 || jobclass == 4043) { - - // job modification - if (jobclass == 19 || jobclass == 20) { - char_class = (sex) ? 19 : 20; - } else if (jobclass == 4020 || jobclass == 4021) { - char_class = (sex) ? 4020 : 4021; - } else if (jobclass == 4042 || jobclass == 4043) { - char_class = (sex) ? 4042 : 4043; - } - - // remove specifical skills of classes 19,20 4020,4021 and 4042,4043 - sprintf(tmp_sql, "SELECT `lv` FROM `%s` WHERE `char_id` = '%d' AND `id` >= '315' AND `id` <= '330'",skill_db, char_id); - sql_query(tmp_sql,"change_sex_reply"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { - while(( sql_row = mysql_fetch_row(sql_res))) { - skill_point += atoi(sql_row[0]); - } - } - - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `char_id` = '%d' AND `id` >= '315' AND `id` <= '330'",skill_db, char_id); - sql_query(tmp_sql,"change_sex_reply"); - - // to avoid any problem with equipment and invalid sex, equipment is unequiped. - sprintf(tmp_sql, "UPDATE `%s` SET `equip` = '0' WHERE `char_id` = '%d'",inventory_db, char_id); - sql_query(tmp_sql,"change_sex_reply"); - - sprintf(tmp_sql, "UPDATE `%s` SET `class`='%d' , `skill_point`='%d' , `weapon`='0' , `shield='0' , `head_top`='0' , `head_mid`='0' , `head_bottom`='0' WHERE `char_id` = '%d'",char_db, char_class, skill_point, char_id); - sql_query(tmp_sql,"change_sex_reply"); - } - } - - // disconnect player if online on char-server - for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data)) { - if (sd->account_id == acc) { - session[i]->eof = 1; - break; - } - } - } - - WBUFW(buf,0) = 0x2b0d; - WBUFL(buf,2) = acc; - WBUFB(buf,6) = sex; - mapif_sendall(buf, 7); - } - - return 0; -} - -int account_reg2(int fd, int len) { - if (len < 4 || len < RFIFOW(fd,2)) - return -1; - - struct global_reg reg[ACCOUNT_REG2_NUM]; - unsigned char buf[4096]; - int j, p, acc; - - acc = RFIFOL(fd,4); - - for(p = 8, j = 0; p < RFIFOW(fd,2) && j < ACCOUNT_REG2_NUM; p += 36, j++) { - memcpy(reg[j].str, RFIFOP(fd,p), 32); - reg[j].value = RFIFOL(fd,p+32); - } - - // set_account_reg2(acc,j,reg); - // “¯CƒƒOƒCƒ“‚ð‹ÖŽ~‚µ‚Ä‚¢‚ê‚Α—‚é•K—v‚Í–³‚¢ - memcpy(buf,RFIFOP(fd,0), RFIFOW(fd,2)); - WBUFW(buf,0) = 0x2b11; - mapif_sendall(buf, WBUFW(buf,2)); - RFIFOSKIP(fd, RFIFOW(fd,2)); - - #ifdef DEBUG - printf("char: save_account_reg_reply\n"); - #endif - - return 0; -} - -// State change of account/ban notification (from login-server) by [Yor] -int change_state_reply(int fd, int len) { - if (len < 11) - return -1; - +int parse_tologin(int fd) { int i; struct char_session_data *sd; - // send to all map-servers to disconnect the player - unsigned char buf[16]; - WBUFW(buf,0) = 0x2b14; - WBUFL(buf,2) = RFIFOL(fd,2); - WBUFB(buf,6) = RFIFOB(fd,6); // 0: change of statut, 1: ban - WBUFL(buf,7) = RFIFOL(fd,7); // status or final date of a banishment - mapif_sendall(buf, 11); - - // disconnect player if online on char-server - for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data)) { - if (sd->account_id == RFIFOL(fd,2)) { - session[i]->eof = 1; - break; - } - } - } - - RFIFOSKIP(fd,11); - - return 0; -} - -int parse_tologin(int fd) { - int len,res = 0; - // only login-server can have an access to here. // so, if it isn't the login-server, we disconnect the session. //session eof check! if(fd != login_fd) session[fd]->eof = 1; - if(session[fd]->eof) { if (fd == login_fd) { printf("Char-server can't connect to login-server (connection #%d).\n", fd); - delete_timer(user_count_timer,send_users_tologin); login_fd = -1; } close(fd); @@ -1475,570 +1472,826 @@ int parse_tologin(int fd) { return 0; } + sd = (struct char_session_data*)session[fd]->session_data; + // hehe. no need to set user limite on SQL version. :P // but char limitation is good way to maintain server. :D - len = RFIFOREST(fd); - while(len >= 2 && res == 0) { - #ifdef DEBUG - printf("parse_tologin : %d %d %x\n", fd, RFIFOREST(fd), RFIFOW(fd, 0)); - #endif + while(RFIFOREST(fd) >= 2) { +// printf("parse_tologin : %d %d %x\n", fd, RFIFOREST(fd), RFIFOW(fd, 0)); switch(RFIFOW(fd, 0)){ - case 0x2711: res = reply_login_request(fd,len); break; - case 0x2713: res = send_chars(fd,len); break; - case 0x2717: res = connect_until_reply(fd,len); break; - case 0x2723: res = change_sex_reply(fd,len); break; - case 0x2729: res = account_reg2(fd,len); break; - case 0x2731: res = change_state_reply(fd,len); break; - case 0x2732: res = read_gm_accounts(fd,len); break; - - default: - printf("set eof.\n"); - session[fd]->eof = 1; - return 0; - } - - len = RFIFOREST(fd); - } - - RFIFOFLUSH(fd); - - return 0; -} - -//-------------------------------- -// Map-server anti-freeze system -//-------------------------------- -int map_anti_freeze_system(int tid, unsigned int tick, int id, int data) { - int i; + case 0x2711: + if (RFIFOREST(fd) < 3) + return 0; + if (RFIFOB(fd, 2)) { + //printf("connect login server error : %d\n", RFIFOB(fd, 2)); + printf("Can not connect to login-server.\n"); + printf("The server communication passwords (default s1/p1) is probably invalid.\n"); + printf("Also, please make sure your login db has the username/password present and the sex of the account is S.\n"); + printf("If you changed the communication passwords, change them back at map_athena.conf and char_athena.conf\n"); + return 0; + //exit(1); //fixed for server shutdown. + }else { + printf("Connected to login-server (connection #%d).\n", fd); + set_all_offline(); + // if no map-server already connected, display a message... + for(i = 0; i < MAX_MAP_SERVERS; i++) + if (server_fd[i] >= 0 && server[i].map[0][0]) // if map-server online and at least 1 map + break; + if (i == MAX_MAP_SERVERS) + printf("Awaiting maps from map-server.\n"); + } + RFIFOSKIP(fd, 3); + break; - for(i = 0; i < MAX_MAP_SERVERS; i++) { - if (server_fd[i] >= 0) {// if map-server is online - printf("map_anti_freeze_system: server #%d, flag: %d.\n", i, server_freezeflag[i]); - if (server_freezeflag[i]-- < 1) {// Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed - printf("Map-server anti-freeze system: char-server #%d is frozen -> disconnection.\n", i); - session[server_fd[i]]->eof = 1; - sprintf(tmp_sql, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server_fd[i]); - if (mysql_query(&mysql_handle, tmp_sql)) { - printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + case 0x2713: + if(RFIFOREST(fd)<51) + return 0; + for(i = 0; i < fd_max; i++) { + if (session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->account_id == RFIFOL(fd,2)) { + if (RFIFOB(fd,6) != 0) { + WFIFOW(i,0) = 0x6c; + WFIFOB(i,2) = 0x42; + WFIFOSET(i,3); + } else if (max_connect_user == 0 || count_users() < max_connect_user) { +// if (max_connect_user == 0) +// printf("max_connect_user (unlimited) -> accepted.\n"); +// else +// printf("count_users(): %d < max_connect_user (%d) -> accepted.\n", count_users(), max_connect_user); + sd->connect_until_time = (time_t)RFIFOL(fd,47); + // send characters to player + mmo_char_send006b(i, sd); + } else if(isGM(sd->account_id) >= gm_allow_level) { + sd->connect_until_time = (time_t)RFIFOL(fd,47); + // send characters to player + mmo_char_send006b(i, sd); + } else { + // refuse connection: too much online players +// printf("count_users(): %d < max_connect_use (%d) -> fail...\n", count_users(), max_connect_user); + WFIFOW(i,0) = 0x6c; + WFIFOW(i,2) = 0; + WFIFOSET(i,3); + } } } - } - } - - return 0; -} - -int recv_map_names(int fd, int len, unsigned char id) { - if (len < 4 || len < RFIFOW(fd,2)) - return -1; - - memset(server[id].map, 0, sizeof(server[id].map)); - - int j = 0,i; - unsigned char buf[16384]; - int x; - - for(i = 4; i < RFIFOW(fd,2); i += 16) { - memcpy(server[id].map[j], RFIFOP(fd,i), 16); -// printf("set map %d.%d : %s\n", id, j, server[id].map[j]); - j++; - } - - i = server[id].ip; - - unsigned char *p = (unsigned char *)&server[id].ip; - - printf("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", - id, j, p[0], p[1], p[2], p[3], server[id].port); - - - WFIFOW(fd,0) = 0x2afb; - WFIFOB(fd,2) = 0; - memcpy(WFIFOP(fd,3), wisp_server_name, 24); // name for wisp to player - WFIFOSET(fd,27); - - - if (j == 0) { - printf("WARNING: Map-Server %d have NO maps.\n", id); - } else { - // Transmitting maps information to the other map-servers - WBUFW(buf,0) = 0x2b04; - WBUFW(buf,2) = j * 16 + 10; - WBUFL(buf,4) = server[id].ip; - WBUFW(buf,8) = server[id].port; - memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 16); - mapif_sendallwos(fd, buf, WBUFW(buf,2)); - } - - // Transmitting the maps of the other map-servers to the new map-server - for(x = 0; x < MAX_MAP_SERVERS; x++) { - if (server_fd[x] >= 0 && x != id) { - WFIFOW(fd,0) = 0x2b04; - WFIFOL(fd,4) = server[x].ip; - WFIFOW(fd,8) = server[x].port; + RFIFOSKIP(fd,51); + break; - j = 0; + case 0x2717: + if (RFIFOREST(fd) < 50) + return 0; + for(i = 0; i < fd_max; i++) { + if (session[i] && (sd = (struct char_session_data*)session[i]->session_data)) { + if (sd->account_id == RFIFOL(fd,2)) { + sd->connect_until_time = (time_t)RFIFOL(fd,46); + break; + } + } + } + RFIFOSKIP(fd,50); + break; - for(i = 0; i < MAX_MAP_PER_SERVER; i++) - if (server[x].map[i][0]) - memcpy(WFIFOP(fd,10+(j++)*16), server[x].map[i], 16); + // login-server alive packet + case 0x2718: + if (RFIFOREST(fd) < 2) + return 0; + RFIFOSKIP(fd,2); + break; - if (j > 0) { - WFIFOW(fd,2) = j * 16 + 10; - WFIFOSET(fd,WFIFOW(fd,2)); + // Receiving authentification from Freya-type login server (to avoid char->login->char) + case 0x2719: + if (RFIFOREST(fd) < 18) + return 0; + // to conserv a maximum of authentification, search if account is already authentified and replace it + // that will reduce multiple connection too + for(i = 0; i < AUTH_FIFO_SIZE; i++) + if (auth_fifo[i].account_id == RFIFOL(fd,2)) + break; + // if not found, use next value + if (i == AUTH_FIFO_SIZE) { + if (auth_fifo_pos >= AUTH_FIFO_SIZE) + auth_fifo_pos = 0; + i = auth_fifo_pos; + auth_fifo_pos++; } - } - } - - RFIFOSKIP(fd,RFIFOW(fd,2)); + //printf("auth_fifo set (auth #%d) - account: %d, secure: %08x-%08x\n", i, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); + auth_fifo[i].account_id = RFIFOL(fd,2); + auth_fifo[i].char_id = 0; + auth_fifo[i].login_id1 = RFIFOL(fd,6); + auth_fifo[i].login_id2 = RFIFOL(fd,10); + auth_fifo[i].delflag = 2; // 0: auth_fifo canceled/void, 2: auth_fifo received from login/map server in memory, 1: connection authentified + auth_fifo[i].char_pos = 0; + auth_fifo[i].connect_until_time = 0; // unlimited/unknown time by default (not display in map-server) + auth_fifo[i].ip = RFIFOL(fd,14); + //auth_fifo[i].map_auth = 0; + RFIFOSKIP(fd,18); + break; - printf("Map-server %d loading complete.\n", id); +/* case 0x2721: // gm reply. I don't want to support this function. + printf("0x2721:GM reply\n"); + { + int oldacc, newacc; + unsigned char buf[64]; + if (RFIFOREST(fd) < 10) + return 0; + oldacc = RFIFOL(fd, 2); + newacc = RFIFOL(fd, 6); + RFIFOSKIP(fd, 10); + if (newacc > 0) { + for(i=0;i<char_num;i++){ + if(char_dat[i].account_id==oldacc) + char_dat[i].account_id=newacc; + } + } + WBUFW(buf,0)=0x2b0b; + WBUFL(buf,2)=oldacc; + WBUFL(buf,6)=newacc; + mapif_sendall(buf,10); +// printf("char -> map\n"); + } + break; +*/ + case 0x2723: // changesex reply (modified by [Yor]) + if (RFIFOREST(fd) < 7) + return 0; + { + int acc, sex; + unsigned char buf[16]; + + acc = RFIFOL(fd,2); + sex = RFIFOB(fd,6); + RFIFOSKIP(fd, 7); + if (acc > 0) { + sprintf(tmp_sql, "SELECT `char_id`,`class`,`skill_point` FROM `%s` WHERE `account_id` = '%d'",char_db, acc); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `char`)- %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + + if (sql_res) { + int char_id, jobclass, skill_point, class_; + sql_row = mysql_fetch_row(sql_res); + char_id = atoi(sql_row[0]); + jobclass = atoi(sql_row[1]); + skill_point = atoi(sql_row[2]); + class_ = jobclass; + if (jobclass == 19 || jobclass == 20 || + jobclass == 4020 || jobclass == 4021 || + jobclass == 4042 || jobclass == 4043) { + // job modification + if (jobclass == 19 || jobclass == 20) { + class_ = (sex) ? 19 : 20; + } else if (jobclass == 4020 || jobclass == 4021) { + class_ = (sex) ? 4020 : 4021; + } else if (jobclass == 4042 || jobclass == 4043) { + class_ = (sex) ? 4042 : 4043; + } + // remove specifical skills of classes 19,20 4020,4021 and 4042,4043 + sprintf(tmp_sql, "SELECT `lv` FROM `%s` WHERE `char_id` = '%d' AND `id` >= '315' AND `id` <= '330'",skill_db, char_id); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `char`)- %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { + while(( sql_row = mysql_fetch_row(sql_res))) { + skill_point += atoi(sql_row[0]); + } + } + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `char_id` = '%d' AND `id` >= '315' AND `id` <= '330'",skill_db, char_id); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `char`)- %s\n", mysql_error(&mysql_handle)); + } + } + // to avoid any problem with equipment and invalid sex, equipment is unequiped. + sprintf(tmp_sql, "UPDATE `%s` SET `equip` = '0' WHERE `char_id` = '%d'",inventory_db, char_id); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `char`)- %s\n", mysql_error(&mysql_handle)); + } + sprintf(tmp_sql, "UPDATE `%s` SET `class`='%d' , `skill_point`='%d' , `weapon`='0' , `shield='0' , `head_top`='0' , `head_mid`='0' , `head_bottom`='0' WHERE `char_id` = '%d'",char_db, class_, skill_point, char_id); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `char`)- %s\n", mysql_error(&mysql_handle)); + } + } + } + // disconnect player if online on char-server + for(i = 0; i < fd_max; i++) { + if (session[i] && (sd = (struct char_session_data*)session[i]->session_data)) { + if (sd->account_id == acc) { + session[i]->eof = 1; + break; + } + } + } - servers_connected++; + WBUFW(buf,0) = 0x2b0d; + WBUFL(buf,2) = acc; + WBUFB(buf,6) = sex; - return 0; -} + mapif_sendall(buf, 7); + } + break; -int auth_request(int fd, int len) { - if (len < 22) - return -1; + // account_reg2•ÏX’Ê’m + case 0x2729: + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + { + struct global_reg reg[ACCOUNT_REG2_NUM]; + unsigned char buf[4096]; + int j, p, acc; + acc = RFIFOL(fd,4); + for(p = 8, j = 0; p < RFIFOW(fd,2) && j < ACCOUNT_REG2_NUM; p += 36, j++) { + memcpy(reg[j].str, RFIFOP(fd,p), 32); + reg[j].value = RFIFOL(fd,p+32); + } + // set_account_reg2(acc,j,reg); + // “¯CƒƒOƒCƒ“‚ð‹ÖŽ~‚µ‚Ä‚¢‚ê‚Α—‚é•K—v‚Í–³‚¢ + memcpy(buf,RFIFOP(fd,0), RFIFOW(fd,2)); + WBUFW(buf,0) = 0x2b11; + mapif_sendall(buf, WBUFW(buf,2)); + RFIFOSKIP(fd, RFIFOW(fd,2)); +// printf("char: save_account_reg_reply\n"); + } + break; - int i; + // State change of account/ban notification (from login-server) by [Yor] + case 0x2731: + if (RFIFOREST(fd) < 11) + return 0; + // send to all map-servers to disconnect the player + { + unsigned char buf[16]; + WBUFW(buf,0) = 0x2b14; + WBUFL(buf,2) = RFIFOL(fd,2); + WBUFB(buf,6) = RFIFOB(fd,6); // 0: change of statut, 1: ban + WBUFL(buf,7) = RFIFOL(fd,7); // status or final date of a banishment + mapif_sendall(buf, 11); + } + // disconnect player if online on char-server + for(i = 0; i < fd_max; i++) { + if (session[i] && (sd = (struct char_session_data*)session[i]->session_data)) { + if (sd->account_id == RFIFOL(fd,2)) { + session[i]->eof = 1; + break; + } + } + } + RFIFOSKIP(fd,11); + break; - #ifdef DEBUG - printf("(AUTH request) auth_fifo search %d %d %d\n", RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOL(fd, 10)); - #endif + // Receive GM accounts [Freya login server packet by Yor] + case 0x2733: + // add test here to remember that the login-server is Freya-type + // sprintf (login_server_type, "Freya"); + if (RFIFOREST(fd) < 7) + return 0; + { + int new_level = 0; + for(i = 0; i < GM_num; i++) + if (gm_account[i].account_id == RFIFOL(fd,2)) { + if (gm_account[i].level != (int)RFIFOB(fd,6)) { + gm_account[i].level = (int)RFIFOB(fd,6); + new_level = 1; + } + break; + } + // if not found, add it + if (i == GM_num) { + // limited to 4000, because we send information to char-servers (more than 4000 GM accounts???) + // int (id) + int (level) = 8 bytes * 4000 = 32k (limit of packets in windows) + if (((int)RFIFOB(fd,6)) > 0 && GM_num < 4000) { + if (GM_num == 0) { + gm_account = (struct gm_account*)aMalloc(sizeof(struct gm_account)); + } else { + gm_account = (struct gm_account*)aRealloc(gm_account, sizeof(struct gm_account) * (GM_num + 1)); + } + gm_account[GM_num].account_id = RFIFOL(fd,2); + gm_account[GM_num].level = (int)RFIFOB(fd,6); + new_level = 1; + GM_num++; + if (GM_num >= 4000) + printf("***WARNING: 4000 GM accounts found. Next GM accounts are not readed.\n"); + } + } + if (new_level == 1) { + printf("From login-server: receiving a GM account information (%d: level %d).\n", RFIFOL(fd,2), (int)RFIFOB(fd,6)); + mapif_send_gmaccounts(); - for(i = 0; i < AUTH_FIFO_SIZE; i++) { - if (auth_fifo[i].account_id == RFIFOL(fd,2) && - auth_fifo[i].char_id == RFIFOL(fd,6) && - auth_fifo[i].login_id1 == RFIFOL(fd,10) && -#if CMP_AUTHFIFO_LOGIN2 != 0 - // here, it's the only area where it's possible that we doesn't know login_id2 (map-server asks just after 0x72 packet, that doesn't given the value) - (auth_fifo[i].login_id2 == RFIFOL(fd,14) || RFIFOL(fd,14) == 0) && // relate to the versions higher than 18 -#endif - (!check_ip_flag || auth_fifo[i].ip == RFIFOL(fd,18)) && - !auth_fifo[i].delflag) { - - auth_fifo[i].delflag = 1; - WFIFOW(fd,0) = 0x2afd; - WFIFOW(fd,2) = 16 + sizeof(struct mmo_charstatus); - WFIFOL(fd,4) = RFIFOL(fd,2); - WFIFOL(fd,8) = auth_fifo[i].login_id2; - WFIFOL(fd,12) = (unsigned long)auth_fifo[i].connect_until_time; - mmo_char_fromsql(auth_fifo[i].char_id, char_dat, 1); - char_dat[0].sex = auth_fifo[i].sex; - memcpy(WFIFOP(fd,16), &char_dat[0], sizeof(struct mmo_charstatus)); - WFIFOSET(fd, WFIFOW(fd,2)); - - #ifdef DEBUG - printf("auth_fifo search success (auth #%d, account %d, character: %d).\n", i, RFIFOL(fd,2), RFIFOL(fd,6)); - #endif + //create_online_files(); // not change online file for only 1 player (in next timer, that will be done + // send gm acccounts level to map-servers + } + } + RFIFOSKIP(fd,7); + break; + default: + printf("set eof.\n"); + session[fd]->eof = 1; return 0; } } - if (i == AUTH_FIFO_SIZE) { - WFIFOW(fd,0) = 0x2afe; - WFIFOL(fd,2) = RFIFOL(fd,2); - WFIFOSET(fd,6); - - #ifdef DEBUG - printf("(AUTH request) auth_fifo search error!\n"); - #endif - } - - RFIFOSKIP(fd,22); - - return 0; -} - -int set_map_users(int fd, int len, unsigned char id) { - if (len < 6 || len < RFIFOW(fd,2)) - return -1; - - if (RFIFOW(fd,4) != server[id].users) - printf("map user: %d\n", RFIFOW(fd,4)); - - server[id].users = RFIFOW(fd,4); - - if(anti_freeze_enable) - server_freezeflag[id] = 5; // Map anti-freeze system. Counter. 5 ok, 4...0 freezed - - RFIFOSKIP(fd,RFIFOW(fd,2)); + RFIFOFLUSH(fd); return 0; } -int save_char(int fd, int len) { - if (len < 4 || len < RFIFOW(fd,2)) - return -1; +int parse_frommap(int fd) { + int i = 0, j = 0; + int id; - //check account - sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'",char_db, RFIFOL(fd,4),RFIFOL(fd,8)); - sql_query(tmp_sql,"save_char"); + // Sometimes fd=0, and it will cause server crash. Don't know why. :( + if (fd <= 0) { + printf("parse_frommap error fd=0\n"); + return 0; + } - if ((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) - if (atoi(sql_row[0]) == 1) { - memcpy(&char_dat[0], RFIFOP(fd,12), sizeof(struct mmo_charstatus)); - mmo_char_tosql(RFIFOL(fd,8), char_dat); + for(id = 0; id < MAX_MAP_SERVERS; id++) + if (server_fd[id] == fd) + break; + if(id == MAX_MAP_SERVERS) + session[fd]->eof = 1; + if(session[fd]->eof) { + if (id < MAX_MAP_SERVERS) { + memset(&server[id], 0, sizeof(struct mmo_map_server)); + printf("Map-server %d (session #%d) has disconnected.\n", id, fd); + sprintf(tmp_sql, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server_fd[id]); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + server_fd[id] = -1; } + close(fd); + delete_session(fd); + return 0; + } - mysql_free_result(sql_res); - - - RFIFOSKIP(fd,RFIFOW(fd,2)); - - return 0; -} - -int request_char_select(int fd, int len) { - if (len < 18) - return -1; - - if (auth_fifo_pos >= AUTH_FIFO_SIZE) - auth_fifo_pos = 0; - - #ifdef DEBUG - printf("(charselect) auth_fifo set %d - account_id:%08x login_id1:%08x\n", auth_fifo_pos, RFIFOL(fd, 2), RFIFOL(fd, 6)); - #endif - - auth_fifo[auth_fifo_pos].account_id = RFIFOL(fd, 2); - auth_fifo[auth_fifo_pos].char_id = 0; - auth_fifo[auth_fifo_pos].login_id1 = RFIFOL(fd, 6); - auth_fifo[auth_fifo_pos].login_id2 = RFIFOL(fd,10); - auth_fifo[auth_fifo_pos].delflag = 2; - auth_fifo[auth_fifo_pos].char_pos = 0; - auth_fifo[auth_fifo_pos].connect_until_time = 0; // unlimited/unknown time by default (not display in map-server) - auth_fifo[auth_fifo_pos].ip = RFIFOL(fd,14); - auth_fifo_pos++; - - WFIFOW(fd, 0) = 0x2b03; - WFIFOL(fd, 2) = RFIFOL(fd, 2); - WFIFOB(fd, 6) = 0; - WFIFOSET(fd, 7); - - RFIFOSKIP(fd, 18); - - return 0; -} - -int request_change_map(int fd, int len) { - if (len < 49) - return -1; - - if (auth_fifo_pos >= AUTH_FIFO_SIZE) - auth_fifo_pos = 0; - - WFIFOW(fd, 0) = 0x2b06; - memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 42); - - #ifdef DEBUG - printf("(map change) auth_fifo set %d - account_id:%08x login_id1:%08x\n", auth_fifo_pos, RFIFOL(fd, 2), RFIFOL(fd, 6)); - #endif + while(RFIFOREST(fd) >= 2) { +// printf("parse_frommap : %d %d %x\n", fd, RFIFOREST(fd), RFIFOW(fd,0)); - auth_fifo[auth_fifo_pos].account_id = RFIFOL(fd, 2); - auth_fifo[auth_fifo_pos].login_id1 = RFIFOL(fd, 6); - auth_fifo[auth_fifo_pos].login_id2 = RFIFOL(fd,10); - auth_fifo[auth_fifo_pos].char_id = RFIFOL(fd,14); - auth_fifo[auth_fifo_pos].delflag = 0; - auth_fifo[auth_fifo_pos].sex = RFIFOB(fd,44); - auth_fifo[auth_fifo_pos].ip = RFIFOL(fd,45); + switch(RFIFOW(fd, 0)) { - sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", char_db, RFIFOL(fd,2), RFIFOL(fd,14)); - sql_query(tmp_sql,"request_map_change"); + // map-server alive packet + case 0x2718: + if (RFIFOREST(fd) < 2) + return 0; + RFIFOSKIP(fd,2); + break; - if ((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) { + case 0x2af7: + RFIFOSKIP(fd,2); + read_gm_account(); + break; - auth_fifo[auth_fifo_pos].char_pos = auth_fifo[auth_fifo_pos].char_id; - auth_fifo_pos++; + // mapserver -> map names recv. + case 0x2afa: + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + memset(server[id].map, 0, sizeof(server[id].map)); + j = 0; + for(i = 4; i < RFIFOW(fd,2); i += 16) { + memcpy(server[id].map[j], RFIFOP(fd,i), 16); +// printf("set map %d.%d : %s\n", id, j, server[id].map[j]); + j++; + } + i = server[id].ip; + { + unsigned char *p = (unsigned char *)&server[id].ip; + printf("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", + id, j, p[0], p[1], p[2], p[3], server[id].port); + printf("Map-server %d loading complete.\n", id); + set_all_offline(); + } + WFIFOW(fd,0) = 0x2afb; + WFIFOB(fd,2) = 0; + memcpy(WFIFOP(fd,3), wisp_server_name, 24); // name for wisp to player + WFIFOSET(fd,27); + { + unsigned char buf[16384]; + int x; + if (j == 0) { + printf("WARNING: Map-Server %d have NO maps.\n", id); + // Transmitting maps information to the other map-servers + } else { + WBUFW(buf,0) = 0x2b04; + WBUFW(buf,2) = j * 16 + 10; + WBUFL(buf,4) = server[id].ip; + WBUFW(buf,8) = server[id].port; + memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 16); + mapif_sendallwos(fd, buf, WBUFW(buf,2)); + } + // Transmitting the maps of the other map-servers to the new map-server + for(x = 0; x < MAX_MAP_SERVERS; x++) { + if (server_fd[x] >= 0 && x != id) { + WFIFOW(fd,0) = 0x2b04; + WFIFOL(fd,4) = server[x].ip; + WFIFOW(fd,8) = server[x].port; + j = 0; + for(i = 0; i < MAX_MAP_PER_SERVER; i++) + if (server[x].map[i][0]) + memcpy(WFIFOP(fd,10+(j++)*16), server[x].map[i], 16); + if (j > 0) { + WFIFOW(fd,2) = j * 16 + 10; + WFIFOSET(fd,WFIFOW(fd,2)); + } + } + } + } + RFIFOSKIP(fd,RFIFOW(fd,2)); + break; - WFIFOL(fd,6) = 0; - } + // auth request + case 0x2afc: + if (RFIFOREST(fd) < 22) + return 0; +// printf("(AUTH request) auth_fifo search %d %d %d\n", RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOL(fd, 10)); + for(i = 0; i < AUTH_FIFO_SIZE; i++) { + if (auth_fifo[i].account_id == RFIFOL(fd,2) && + auth_fifo[i].char_id == RFIFOL(fd,6) && + auth_fifo[i].login_id1 == RFIFOL(fd,10) && +#if CMP_AUTHFIFO_LOGIN2 != 0 + // here, it's the only area where it's possible that we doesn't know login_id2 (map-server asks just after 0x72 packet, that doesn't given the value) + (auth_fifo[i].login_id2 == RFIFOL(fd,14) || RFIFOL(fd,14) == 0) && // relate to the versions higher than 18 +#endif + (!check_ip_flag || auth_fifo[i].ip == RFIFOL(fd,18)) && + !auth_fifo[i].delflag) { + auth_fifo[i].delflag = 1; + WFIFOW(fd,0) = 0x2afd; + WFIFOW(fd,2) = 16 + sizeof(struct mmo_charstatus); + WFIFOL(fd,4) = RFIFOL(fd,2); + WFIFOL(fd,8) = auth_fifo[i].login_id2; + WFIFOL(fd,12) = (unsigned long)auth_fifo[i].connect_until_time; + mmo_char_fromsql(auth_fifo[i].char_id, char_dat, 1); + char_dat[0].sex = auth_fifo[i].sex; + memcpy(WFIFOP(fd,16), &char_dat[0], sizeof(struct mmo_charstatus)); + WFIFOSET(fd, WFIFOW(fd,2)); + //printf("auth_fifo search success (auth #%d, account %d, character: %d).\n", i, RFIFOL(fd,2), RFIFOL(fd,6)); + break; + } + } + if (i == AUTH_FIFO_SIZE) { + WFIFOW(fd,0) = 0x2afe; + WFIFOL(fd,2) = RFIFOL(fd,2); + WFIFOSET(fd,6); +// printf("(AUTH request) auth_fifo search error!\n"); + } + RFIFOSKIP(fd,22); + break; - if (atoi(sql_row[0]) == 0) - WFIFOW(fd,6) = 1; + // set MAP user + case 0x2aff: + if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + if (RFIFOW(fd,4) != server[id].users) + printf("[UserCount]: %d (Server: %d)\n", RFIFOW(fd,4), id); + server[id].users = RFIFOW(fd,4); + RFIFOSKIP(fd,RFIFOW(fd,2)); + break; - WFIFOSET(fd,44); - RFIFOSKIP(fd,49); + // char saving + case 0x2b01: + i = 0; + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + //check account + sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'",char_db, RFIFOL(fd,4),RFIFOL(fd,8)); // TBR + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); + if (sql_row) + i = atoi(sql_row[0]); + } + mysql_free_result(sql_res); - mysql_free_result(sql_res); + if (i == 1) { + memcpy(&char_dat[0], RFIFOP(fd,12), sizeof(struct mmo_charstatus)); + mmo_char_tosql(RFIFOL(fd,8), char_dat); + //save to DB + } + RFIFOSKIP(fd,RFIFOW(fd,2)); + break; - return 0; -} + // req char selection + case 0x2b02: + if (RFIFOREST(fd) < 18) + return 0; -int char_name_check(int fd, int len) { - if (len < 6) - return -1; + if (auth_fifo_pos >= AUTH_FIFO_SIZE) + auth_fifo_pos = 0; + +// printf("(charselect) auth_fifo set %d - account_id:%08x login_id1:%08x\n", auth_fifo_pos, RFIFOL(fd, 2), RFIFOL(fd, 6)); + auth_fifo[auth_fifo_pos].account_id = RFIFOL(fd, 2); + auth_fifo[auth_fifo_pos].char_id = 0; + auth_fifo[auth_fifo_pos].login_id1 = RFIFOL(fd, 6); + auth_fifo[auth_fifo_pos].login_id2 = RFIFOL(fd,10); + auth_fifo[auth_fifo_pos].delflag = 2; + auth_fifo[auth_fifo_pos].char_pos = 0; + auth_fifo[auth_fifo_pos].connect_until_time = 0; // unlimited/unknown time by default (not display in map-server) + auth_fifo[auth_fifo_pos].ip = RFIFOL(fd,14); + auth_fifo_pos++; + + WFIFOW(fd, 0) = 0x2b03; + WFIFOL(fd, 2) = RFIFOL(fd, 2); + WFIFOB(fd, 6) = 0; + WFIFOSET(fd, 7); + + RFIFOSKIP(fd, 18); + break; - WFIFOW(fd,0) = 0x2b09; - WFIFOL(fd,2) = RFIFOL(fd,2); + // request "change map server" + case 0x2b05: + if (RFIFOREST(fd) < 49) + return 0; - sprintf(tmp_sql, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", char_db, RFIFOL(fd,2)); - sql_query(tmp_sql,"char_name_check"); + if (auth_fifo_pos >= AUTH_FIFO_SIZE) + auth_fifo_pos = 0; + + WFIFOW(fd, 0) = 0x2b06; + memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 42); +// printf("(map change) auth_fifo set %d - account_id:%08x login_id1:%08x\n", auth_fifo_pos, RFIFOL(fd, 2), RFIFOL(fd, 6)); + printf("[MapChange] "); + auth_fifo[auth_fifo_pos].account_id = RFIFOL(fd, 2); + auth_fifo[auth_fifo_pos].login_id1 = RFIFOL(fd, 6); + auth_fifo[auth_fifo_pos].login_id2 = RFIFOL(fd,10); + auth_fifo[auth_fifo_pos].char_id = RFIFOL(fd,14); + auth_fifo[auth_fifo_pos].delflag = 0; + auth_fifo[auth_fifo_pos].sex = RFIFOB(fd,44); + auth_fifo[auth_fifo_pos].ip = RFIFOL(fd,45); + + sprintf(tmp_sql, "SELECT `char_id`, `name` FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", char_db, RFIFOL(fd,2), RFIFOL(fd,14)); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + if(sql_res){ + i = atoi(sql_row[0]); + printf("aid: %d, cid: %d, name: %s", RFIFOL(fd,2), atoi(sql_row[0]), sql_row[1]); + mysql_free_result(sql_res); + auth_fifo[auth_fifo_pos].char_pos = auth_fifo[auth_fifo_pos].char_id; + auth_fifo_pos++; + WFIFOL(fd,6) = 0; + }else{ + printf("Error, aborted\n"); + return 0; + } + + if(i == 0){ + WFIFOW(fd, 6) = 0; + } + + WFIFOSET(fd, 44); + RFIFOSKIP(fd, 49); + printf(" done.\n"); + /* + if (( sql_row = mysql_fetch_row(sql_res))) { + i = atoi(sql_row[0]); + mysql_free_result(sql_res); + + auth_fifo[auth_fifo_pos].char_pos = auth_fifo[auth_fifo_pos].char_id; + auth_fifo_pos++; + + WFIFOL(fd,6) = 0; + break; + } + if (i == 0) + WFIFOW(fd,6) = 1; - if((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) - memcpy(WFIFOP(fd,6), sql_row[0], 24); - else - memcpy(WFIFOP(fd,6), unknown_char_name, 24); + WFIFOSET(fd,44); + RFIFOSKIP(fd,49); + break; + */ - mysql_free_result(sql_res); + break; + + // char name check + case 0x2b08: + if (RFIFOREST(fd) < 6) + return 0; - WFIFOSET(fd,30); + sprintf(tmp_sql, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", char_db, RFIFOL(fd,2)); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); - RFIFOSKIP(fd,6); + sql_row = mysql_fetch_row(sql_res); - return 0; -} + WFIFOW(fd,0) = 0x2b09; + WFIFOL(fd,2) = RFIFOL(fd,2); -int account_reg(int fd, int len) { - if (len < 4 || len < RFIFOW(fd,2)) - return -1; + if (sql_row) + memcpy(WFIFOP(fd,6), sql_row[0], 24); + else + memcpy(WFIFOP(fd,6), unknown_char_name, 24); + mysql_free_result(sql_res); - struct global_reg reg[ACCOUNT_REG2_NUM]; - int j,p,acc; - acc=RFIFOL(fd,4); - for(p=8,j=0;p<RFIFOW(fd,2) && j<ACCOUNT_REG2_NUM;p+=36,j++){ - memcpy(reg[j].str,RFIFOP(fd,p),32); - reg[j].value=RFIFOL(fd,p+32); - } + WFIFOSET(fd,30); - // set_account_reg2(acc,j,reg); - // loginƒT[ƒo[‚Ö‘—‚é - if (login_fd > 0) { // don't send request if no login-server - WFIFOW(login_fd, 0) = 0x2728; - memcpy(WFIFOP(login_fd,0), RFIFOP(fd,0), RFIFOW(fd,2)); - WFIFOSET(login_fd, WFIFOW(login_fd,2)); - } + RFIFOSKIP(fd,6); + break; - // ƒ[ƒ‹ƒh‚Ö‚Ì“¯CƒƒOƒCƒ“‚ª‚È‚¯‚ê‚ÎmapƒT[ƒo[‚É‘—‚é•K—v‚͂Ȃ¢ - //memcpy(buf,RFIFOP(fd,0),RFIFOW(fd,2)); - //WBUFW(buf,0)=0x2b11; - //mapif_sendall(buf,WBUFW(buf,2)); - RFIFOSKIP(fd,RFIFOW(fd,2)); +/* // I want become GM - fuck! + case 0x2b0a: + if(RFIFOREST(fd)<4) + return 0; + if(RFIFOREST(fd)<RFIFOW(fd,2)) + return 0; + memcpy(WFIFOP(login_fd,2),RFIFOP(fd,2),RFIFOW(fd,2)-2); + WFIFOW(login_fd,0)=0x2720; + WFIFOSET(login_fd,RFIFOW(fd,2)); +// printf("char : change gm -> login %d %s %d\n", RFIFOL(fd, 4), RFIFOP(fd, 8), RFIFOW(fd, 2)); + RFIFOSKIP(fd, RFIFOW(fd, 2)); + break; + */ + // account_reg•Û‘¶—v‹ + case 0x2b10: + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + { + struct global_reg reg[ACCOUNT_REG2_NUM]; + int j,p,acc; + acc=RFIFOL(fd,4); + for(p=8,j=0;p<RFIFOW(fd,2) && j<ACCOUNT_REG2_NUM;p+=36,j++){ + memcpy(reg[j].str,RFIFOP(fd,p),32); + reg[j].value=RFIFOL(fd,p+32); + } + // set_account_reg2(acc,j,reg); + // loginƒT[ƒo[‚Ö‘—‚é + if (login_fd > 0) { // don't send request if no login-server + WFIFOW(login_fd, 0) = 0x2728; + memcpy(WFIFOP(login_fd,0), RFIFOP(fd,0), RFIFOW(fd,2)); + WFIFOSET(login_fd, WFIFOW(login_fd,2)); + } + // ƒ[ƒ‹ƒh‚Ö‚Ì“¯CƒƒOƒCƒ“‚ª‚È‚¯‚ê‚ÎmapƒT[ƒo[‚É‘—‚é•K—v‚͂Ȃ¢ + //memcpy(buf,RFIFOP(fd,0),RFIFOW(fd,2)); + //WBUFW(buf,0)=0x2b11; + //mapif_sendall(buf,WBUFW(buf,2)); + RFIFOSKIP(fd,RFIFOW(fd,2)); // printf("char: save_account_reg (from map)\n"); + } + break; - return 0; -} - -// Map server send information to change an email of an account -> login-server -int change_email_request(int fd, int len) { - if (len < 86) - return -1; - - if (login_fd > 0) { // don't send request if no login-server - memcpy(WFIFOP(login_fd,0), RFIFOP(fd,0), 86); // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B - WFIFOW(login_fd,0) = 0x2722; - WFIFOSET(login_fd, 86); - } - - RFIFOSKIP(fd, 86); - - return 0; -} + // Map server send information to change an email of an account -> login-server + case 0x2b0c: + if (RFIFOREST(fd) < 86) + return 0; + if (login_fd > 0) { // don't send request if no login-server + memcpy(WFIFOP(login_fd,0), RFIFOP(fd,0), 86); // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B + WFIFOW(login_fd,0) = 0x2722; + WFIFOSET(login_fd, 86); + } + RFIFOSKIP(fd, 86); + break; -// Receiving from map-server a status change resquest. Transmission to login-server (by Yor) -int status_change_request(int fd, int len) { - if (len < 44) - return -1; + // Receiving from map-server a status change resquest. Transmission to login-server (by Yor) + case 0x2b0e: + if (RFIFOREST(fd) < 44) + return 0; + { + char character_name[24]; + int acc = RFIFOL(fd,2); // account_id of who ask (-1 if nobody) + memcpy(character_name, RFIFOP(fd,6), 24); + character_name[sizeof(character_name) -1] = '\0'; + // prepare answer + WFIFOW(fd,0) = 0x2b0f; // answer + WFIFOL(fd,2) = acc; // who want do operation + WFIFOW(fd,30) = RFIFOW(fd, 30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban + sprintf(tmp_sql, "SELECT `account_id`,`name` FROM `%s` WHERE `name` = '%s'",char_db, character_name); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error (select `char`)- %s\n", mysql_error(&mysql_handle)); + } - char character_name[24]; - int acc = RFIFOL(fd,2); // account_id of who ask (-1 if nobody) - - memcpy(character_name, RFIFOP(fd,6), 24); - character_name[sizeof(character_name) -1] = '\0'; - - // prepare answer - WFIFOW(fd,0) = 0x2b0f; // answer - WFIFOL(fd,2) = acc; // who want do operation - WFIFOW(fd,30) = RFIFOW(fd, 30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban - - sprintf(tmp_sql, "SELECT `account_id`,`name` FROM `%s` WHERE `name` = '%s'",char_db, character_name); - sql_query(tmp_sql,"status_change_request"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { - if ((sql_row = mysql_fetch_row(sql_res))) { - memcpy(WFIFOP(fd,6), sql_row[1], 24); // put correct name if found - WFIFOW(fd,32) = 0; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - - switch(RFIFOW(fd, 30)) { - case 1: // block - if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { - if (login_fd > 0) { // don't send request if no login-server - WFIFOW(login_fd,0) = 0x2724; - WFIFOL(login_fd,2) = atoi(sql_row[0]); // account value - WFIFOL(login_fd,6) = 5; // status of the account - WFIFOSET(login_fd, 10); -// printf("char : status -> login: account %d, status: %d \n", char_dat[i].account_id, 5); + sql_res = mysql_store_result(&mysql_handle); + + if (sql_res) { + if (mysql_num_rows(sql_res)) { + sql_row = mysql_fetch_row(sql_res); + memcpy(WFIFOP(fd,6), sql_row[1], 24); // put correct name if found + WFIFOW(fd,32) = 0; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + switch(RFIFOW(fd, 30)) { + case 1: // block + if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { + if (login_fd > 0) { // don't send request if no login-server + WFIFOW(login_fd,0) = 0x2724; + WFIFOL(login_fd,2) = atoi(sql_row[0]); // account value + WFIFOL(login_fd,6) = 5; // status of the account + WFIFOSET(login_fd, 10); +// printf("char : status -> login: account %d, status: %d \n", char_dat[i].account_id, 5); + } else + WFIFOW(fd,32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline } else - WFIFOW(fd,32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - } else - WFIFOW(fd,32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - break; - case 2: // ban - if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { - if (login_fd > 0) { // don't send request if no login-server - WFIFOW(login_fd, 0) = 0x2725; - WFIFOL(login_fd, 2) = atoi(sql_row[0]); // account value - WFIFOW(login_fd, 6) = RFIFOW(fd,32); // year - WFIFOW(login_fd, 8) = RFIFOW(fd,34); // month - WFIFOW(login_fd,10) = RFIFOW(fd,36); // day - WFIFOW(login_fd,12) = RFIFOW(fd,38); // hour - WFIFOW(login_fd,14) = RFIFOW(fd,40); // minute - WFIFOW(login_fd,16) = RFIFOW(fd,42); // second - WFIFOSET(login_fd,18); -// printf("char : status -> login: account %d, ban: %dy %dm %dd %dh %dmn %ds\n", -// char_dat[i].account_id, (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), (short)RFIFOW(fd,38), (short)RFIFOW(fd,40), (short)RFIFOW(fd,42)); + WFIFOW(fd,32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + break; + case 2: // ban + if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { + if (login_fd > 0) { // don't send request if no login-server + WFIFOW(login_fd, 0) = 0x2725; + WFIFOL(login_fd, 2) = atoi(sql_row[0]); // account value + WFIFOW(login_fd, 6) = RFIFOW(fd,32); // year + WFIFOW(login_fd, 8) = RFIFOW(fd,34); // month + WFIFOW(login_fd,10) = RFIFOW(fd,36); // day + WFIFOW(login_fd,12) = RFIFOW(fd,38); // hour + WFIFOW(login_fd,14) = RFIFOW(fd,40); // minute + WFIFOW(login_fd,16) = RFIFOW(fd,42); // second + WFIFOSET(login_fd,18); +// printf("char : status -> login: account %d, ban: %dy %dm %dd %dh %dmn %ds\n", +// char_dat[i].account_id, (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), (short)RFIFOW(fd,38), (short)RFIFOW(fd,40), (short)RFIFOW(fd,42)); + } else + WFIFOW(fd,32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline } else - WFIFOW(fd,32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - } else - WFIFOW(fd,32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - break; - case 3: // unblock - if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { - if (login_fd > 0) { // don't send request if no login-server - WFIFOW(login_fd,0) = 0x2724; - WFIFOL(login_fd,2) = atoi(sql_row[0]); // account value - WFIFOL(login_fd,6) = 0; // status of the account - WFIFOSET(login_fd, 10); -// printf("char : status -> login: account %d, status: %d \n", char_dat[i].account_id, 0); + WFIFOW(fd,32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + break; + case 3: // unblock + if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { + if (login_fd > 0) { // don't send request if no login-server + WFIFOW(login_fd,0) = 0x2724; + WFIFOL(login_fd,2) = atoi(sql_row[0]); // account value + WFIFOL(login_fd,6) = 0; // status of the account + WFIFOSET(login_fd, 10); +// printf("char : status -> login: account %d, status: %d \n", char_dat[i].account_id, 0); + } else + WFIFOW(fd,32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline } else - WFIFOW(fd,32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - } else - WFIFOW(fd,32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - break; - case 4: // unban - if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { - if (login_fd > 0) { // don't send request if no login-server - WFIFOW(login_fd, 0) = 0x272a; - WFIFOL(login_fd, 2) = atoi(sql_row[0]); // account value - WFIFOSET(login_fd, 6); -// printf("char : status -> login: account %d, unban request\n", char_dat[i].account_id); + WFIFOW(fd,32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + break; + case 4: // unban + if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { + if (login_fd > 0) { // don't send request if no login-server + WFIFOW(login_fd, 0) = 0x272a; + WFIFOL(login_fd, 2) = atoi(sql_row[0]); // account value + WFIFOSET(login_fd, 6); +// printf("char : status -> login: account %d, unban request\n", char_dat[i].account_id); + } else + WFIFOW(fd,32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline } else - WFIFOW(fd,32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - } else - WFIFOW(fd,32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - break; - case 5: // changesex - if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { - if (login_fd > 0) { // don't send request if no login-server - WFIFOW(login_fd, 0) = 0x2727; - WFIFOL(login_fd, 2) = atoi(sql_row[0]); // account value - WFIFOSET(login_fd, 6); -// printf("char : status -> login: account %d, change sex request\n", char_dat[i].account_id); + WFIFOW(fd,32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + break; + case 5: // changesex + if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { + if (login_fd > 0) { // don't send request if no login-server + WFIFOW(login_fd, 0) = 0x2727; + WFIFOL(login_fd, 2) = atoi(sql_row[0]); // account value + WFIFOSET(login_fd, 6); +// printf("char : status -> login: account %d, change sex request\n", char_dat[i].account_id); + } else + WFIFOW(fd,32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline } else - WFIFOW(fd,32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - } else - WFIFOW(fd,32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - break; - } - } else { - // character name not found - memcpy(WFIFOP(fd,6), character_name, 24); - WFIFOW(fd,32) = 1; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - } - - // send answer if a player ask, not if the server ask - if (acc != -1) { - WFIFOSET(fd, 34); - } - } - - RFIFOSKIP(fd, 44); - - return 0; -} - -int recieve_rates(int fd, int len) { - if (len < 6 || len < RFIFOW(fd,8)) - return -1; - - sprintf(tmp_sql, "INSERT INTO `ragsrvinfo` SET `index`='%d',`name`='%s',`exp`='%d',`jexp`='%d',`drop`='%d',`motd`='%s'", - fd, server_name, RFIFOW(fd,2), RFIFOW(fd,4), RFIFOW(fd,6), RFIFOP(fd,10)); - sql_query(tmp_sql,"recieve_rates"); - - RFIFOSKIP(fd,RFIFOW(fd,8)); - - return 0; -} - -int set_offline(int fd, int len) { - if (len < 6 ) - return -1; - - #ifdef DEBUG - printf("Setting [%d] char offline\n",RFIFOL(fd,2)); - #endif - - sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `char_id`='%d'", char_db, RFIFOL(fd,2)); - sql_query(tmp_sql,"set_offline"); - - RFIFOSKIP(fd,6); - - return 0; -} - -int parse_frommap(int fd) { - int len,res=0; - unsigned char id; - - // Sometimes fd=0, and it will cause server crash. Don't know why. :( - if (fd <= 0) { - printf("parse_frommap error fd=0\n"); - return 0; - } - - for(id = 0; id < MAX_MAP_SERVERS && id < servers_connected; id++) - if (server_fd[id] == fd) + WFIFOW(fd,32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + break; + } + } else { + // character name not found + memcpy(WFIFOP(fd,6), character_name, 24); + WFIFOW(fd,32) = 1; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + } + // send answer if a player ask, not if the server ask + if (acc != -1) { + WFIFOSET(fd, 34); + } + } + } + RFIFOSKIP(fd, 44); break; - if(id == MAX_MAP_SERVERS || !servers_connected) - session[fd]->eof = 1; - - if(session[fd]->eof) { - if (servers_connected) { - memset(&server[id], 0, sizeof(struct mmo_map_server)); - - printf("Map-server %d (session #%d) has disconnected.\n", id, fd); - - sprintf(tmp_sql, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server_fd[id]); - sql_query(tmp_sql,"parse_frommap"); - - server_fd[id] = -1; - - servers_connected--; - } - close(fd); - delete_session(fd); - return 0; - } - - len = RFIFOREST(fd); + // Recieve rates [Wizputer] + case 0x2b16: + if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,8)) + return 0; + sprintf(tmp_sql, "INSERT INTO `ragsrvinfo` SET `index`='%d',`name`='%s',`exp`='%d',`jexp`='%d',`drop`='%d',`motd`='%s'", + fd, server_name, RFIFOW(fd,2), RFIFOW(fd,4), RFIFOW(fd,6), RFIFOP(fd,10)); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + RFIFOSKIP(fd,RFIFOW(fd,8)); + break; - while(len >= 2 && res == 0) { - #ifdef DEBUG - printf("parse_frommap : %d %d %x\n", fd, RFIFOREST(fd), RFIFOW(fd,0)); - #endif + // Character disconnected set online 0 [Wizputer] + case 0x2b17: + if (RFIFOREST(fd) < 6 ) + return 0; + //printf("Setting %d char offline\n",RFIFOL(fd,2)); + set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6)); + RFIFOSKIP(fd,10); + break; + // Reset all chars to offline [Wizputer] + case 0x2b18: + set_all_offline(); + RFIFOSKIP(fd,2); + break; + // Character set online [Wizputer] + case 0x2b19: + if (RFIFOREST(fd) < 6 ) + return 0; + //printf("Setting %d char online\n",RFIFOL(fd,2)); + set_char_online(RFIFOL(fd,2),RFIFOL(fd,6)); + RFIFOSKIP(fd,10); + break; - switch(RFIFOW(fd, 0)) { - case 0x2af7: res = read_gm_accounts(fd,len); break; - case 0x2afa: res = recv_map_names(fd,len,id); break; - case 0x2afc: res = auth_request(fd,len); break; - case 0x2aff: res = set_map_users(fd,len,id); break; - case 0x2b01: res = save_char(fd,len); break; - case 0x2b02: res = request_char_select(fd,len); break; - case 0x2b05: res = request_change_map(fd,len); break; - case 0x2b08: res = char_name_check(fd,len); break; - case 0x2b10: res = account_reg(fd,len); break; - case 0x2b0c: res = change_email_request(fd,len); break; - case 0x2b0e: res = status_change_request(fd,len); break; - case 0x2b16: res = recieve_rates(fd,len); break; - case 0x2b17: res = set_offline(fd,len); break; - - default: + default: // inter server - packet { int r = inter_parse_frommap(fd); @@ -2051,8 +2304,6 @@ int parse_frommap(int fd) { session[fd]->eof = 1; return 0; } - - len = RFIFOREST(fd); } return 0; } @@ -2069,7 +2320,7 @@ int search_mapserver(char *map) { temp_map[strchr(temp_map, '.') - temp_map + 1] = '\0'; // suppress the '.gat', but conserve the '.' to be sure of the name of the map temp_map_len = strlen(temp_map); - for(i = 0; i < MAX_MAP_SERVERS && i < servers_connected; i++) + for(i = 0; i < MAX_MAP_SERVERS; i++) if (server_fd[i] >= 0) for (j = 0; server[i].map[j][0]; j++) //printf("%s : %s = %d\n", server[i].map[j], map, strncmp(server[i].map[j], temp_map, temp_map_len)); @@ -2112,470 +2363,568 @@ int lan_ip_check(unsigned char *p){ return lancheck; } -int client_request_connect(int fd, int len) { - if (len < 17) - return -1; - - struct char_session_data *sd = session[fd]->session_data; - int i; +int parse_char(int fd) { + int i, ch = 0; + char email[40]; + unsigned short cmd; + struct char_session_data *sd; + unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr; - #ifdef DEBUG - printf("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOL(fd, 10)); - #endif + sd = (struct char_session_data*)session[fd]->session_data; - if (sd == NULL) { - CREATE(session[fd]->session_data, struct char_session_data, 1); - sd = session[fd]->session_data; - sd->connect_until_time = 0; // unknow or illimited (not displaying on map-server) + if(login_fd < 0) + session[fd]->eof = 1; + if(session[fd]->eof) { + if (fd == login_fd) + login_fd = -1; + if (sd != NULL) + set_char_offline(99,sd->account_id); + close(fd); + delete_session(fd); + return 0; } - sd->account_id = RFIFOL(fd, 2); - sd->login_id1 = RFIFOL(fd, 6); - sd->login_id2 = RFIFOL(fd, 10); - sd->sex = RFIFOB(fd, 16); + while(RFIFOREST(fd) >= 2) { + cmd = RFIFOW(fd,0); + // crc32‚̃XƒLƒbƒv—p + if( sd==NULL && // –¢ƒƒOƒCƒ“orŠÇ—ƒpƒPƒbƒg + RFIFOREST(fd)>=4 && // Å’áƒoƒCƒg”§ŒÀ • 0x7530,0x7532ŠÇ—ƒpƒPœ‹Ž + RFIFOREST(fd)<=21 && // Å‘åƒoƒCƒg”§ŒÀ • ƒT[ƒo[ƒƒOƒCƒ“œ‹Ž + cmd!=0x20b && // md5’Ê’mƒpƒPƒbƒgœ‹Ž + (RFIFOREST(fd)<6 || RFIFOW(fd,4)==0x65) ){ // ŽŸ‚ɉ½‚©ƒpƒPƒbƒg‚ª—ˆ‚Ä‚é‚È‚çAÚ‘±‚łȂ¢‚Æ‚¾‚ß + RFIFOSKIP(fd,4); + cmd = RFIFOW(fd,0); + printf("parse_char : %d crc32 skipped\n",fd); + if(RFIFOREST(fd)==0) + return 0; + } - WFIFOL(fd, 0) = RFIFOL(fd, 2); - WFIFOSET(fd, 4); +// if(cmd<30000 && cmd!=0x187) +// printf("parse_char : %d %d %d\n",fd,RFIFOREST(fd),cmd); - for(i = 0; i < AUTH_FIFO_SIZE; i++) { - if(auth_fifo[i].account_id == sd->account_id && - auth_fifo[i].login_id1 == sd->login_id1 && -#if CMP_AUTHFIFO_LOGIN2 != 0 - auth_fifo[i].login_id2 == sd->login_id2 && // relate to the versions higher than 18 -#endif - (!check_ip_flag || auth_fifo[i].ip == session[fd]->client_addr.sin_addr.s_addr) && - auth_fifo[i].delflag == 2) { - auth_fifo[i].delflag = 1; - - if (max_connect_user == 0 || count_users() < max_connect_user) { - if (login_fd > 0) { // don't send request if no login-server - // request to login-server to obtain e-mail/time limit - WFIFOW(login_fd,0) = 0x2716; - WFIFOL(login_fd,2) = sd->account_id; - WFIFOSET(login_fd,6); - } - - // send characters to player - mmo_char_send006b(fd, sd); - } else { - // refuse connection (over populated) - WFIFOW(fd,0) = 0x6c; - WFIFOW(fd,2) = 0; - WFIFOSET(fd,3); - } - - #ifdef DEBUG - printf("connection request> set delflag 1(o:2)- account_id:%d/login_id1:%d(fifo_id:%d)\n", sd->account_id, sd->login_id1, i); - #endif - - break; - } - } - if (i == AUTH_FIFO_SIZE) { - if (login_fd > 0) { // don't send request if no login-server - WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account - WFIFOL(login_fd,2) = sd->account_id; - WFIFOL(login_fd,6) = sd->login_id1; - WFIFOL(login_fd,10) = sd->login_id2; - WFIFOB(login_fd,14) = sd->sex; - WFIFOL(login_fd,15) = session[fd]->client_addr.sin_addr.s_addr; - WFIFOSET(login_fd,19); - } else { // if no login-server, we must refuse connection - WFIFOW(fd,0) = 0x6c; - WFIFOW(fd,2) = 0; - WFIFOSET(fd,3); - } - } + // •s³ƒpƒPƒbƒg‚̈— +// if (sd == NULL && cmd != 0x65 && cmd != 0x20b && cmd != 0x187 && +// cmd != 0x2af8 && cmd != 0x7530 && cmd != 0x7532) +// cmd = 0xffff; // ƒpƒPƒbƒgƒ_ƒ“ƒv‚ð•\ަ‚³‚¹‚é - #ifdef DEBUG - if (isGM(RFIFOL(fd,2))) - printf("Account Logged On; Account ID: %d (GM level %d).\n", RFIFOL(fd,2), isGM(RFIFOL(fd,2))); - else - printf("Account Logged On; Account ID: %d.\n", RFIFOL(fd,2)); - #endif + switch(cmd){ + case 0x20b: //20040622 encryption ragexe correspondence + if (RFIFOREST(fd) < 19) + return 0; + RFIFOSKIP(fd,19); + break; - RFIFOSKIP(fd, 17); + case 0x65: // request to connect + printf("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOL(fd, 10)); + if (RFIFOREST(fd) < 17) + return 0; + { +/*removed from isGM setup + if (isGM(RFIFOL(fd,2))) + printf("Account Logged On; Account ID: %d (GM level %d).\n", RFIFOL(fd,2), isGM(RFIFOL(fd,2))); + else + printf("Account Logged On; Account ID: %d.\n", RFIFOL(fd,2)); +*/ + if (sd == NULL) { + CREATE(session[fd]->session_data, struct char_session_data, 1); + sd = (struct char_session_data*)session[fd]->session_data; + sd->connect_until_time = 0; // unknow or illimited (not displaying on map-server) + } + sd->account_id = RFIFOL(fd, 2); + sd->login_id1 = RFIFOL(fd, 6); + sd->login_id2 = RFIFOL(fd, 10); + sd->sex = RFIFOB(fd, 16); - return 0; -} + WFIFOL(fd, 0) = RFIFOL(fd, 2); + WFIFOSET(fd, 4); -int char_select(int fd, int len, unsigned char *ip) { - if (len < 3) - return -1; + for(i = 0; i < AUTH_FIFO_SIZE; i++) { + if (auth_fifo[i].account_id == sd->account_id && + auth_fifo[i].login_id1 == sd->login_id1 && +#if CMP_AUTHFIFO_LOGIN2 != 0 + auth_fifo[i].login_id2 == sd->login_id2 && // relate to the versions higher than 18 +#endif + (!check_ip_flag || auth_fifo[i].ip == session[fd]->client_addr.sin_addr.s_addr) && + auth_fifo[i].delflag == 2) { + auth_fifo[i].delflag = 1; + + if (max_connect_user == 0 || count_users() < max_connect_user) { + if (login_fd > 0) { // don't send request if no login-server + // request to login-server to obtain e-mail/time limit + WFIFOW(login_fd,0) = 0x2716; + WFIFOL(login_fd,2) = sd->account_id; + WFIFOSET(login_fd,6); + } + // send characters to player + mmo_char_send006b(fd, sd); + } else { + // refuse connection (over populated) + WFIFOW(fd,0) = 0x6c; + WFIFOW(fd,2) = 0; + WFIFOSET(fd,3); + } +// printf("connection request> set delflag 1(o:2)- account_id:%d/login_id1:%d(fifo_id:%d)\n", sd->account_id, sd->login_id1, i); + break; + } + } + if (i == AUTH_FIFO_SIZE) { + if (login_fd > 0) { // don't send request if no login-server + WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account + WFIFOL(login_fd,2) = sd->account_id; + WFIFOL(login_fd,6) = sd->login_id1; + WFIFOL(login_fd,10) = sd->login_id2; + WFIFOB(login_fd,14) = sd->sex; + WFIFOL(login_fd,15) = session[fd]->client_addr.sin_addr.s_addr; + WFIFOSET(login_fd,19); + } else { // if no login-server, we must refuse connection + WFIFOW(fd,0) = 0x6c; + WFIFOW(fd,2) = 0; + WFIFOSET(fd,3); + } + } + } + RFIFOSKIP(fd, 17); + break; - int i; - struct char_session_data *sd = session[fd]->session_data; + case 0x66: // char select +// printf("0x66> request connect - account_id:%d/char_num:%d\n",sd->account_id,RFIFOB(fd, 2)); + if (RFIFOREST(fd) < 3) + return 0; - #ifdef DEBUG - printf("0x66> request connect - account_id:%d/char_num:%d\n",sd->account_id,RFIFOB(fd, 2)); - #endif + if (sd == NULL) + return 0; - sprintf(tmp_sql, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'",char_db, sd->account_id, RFIFOB(fd, 2)); - sql_query(tmp_sql,"char_select"); + sprintf(tmp_sql, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'",char_db, sd->account_id, RFIFOB(fd, 2)); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); - if ((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) { - mmo_char_fromsql(atoi(sql_row[0]), char_dat, 0); - mysql_free_result(sql_res); - } else { - mysql_free_result(sql_res); - RFIFOSKIP(fd, 3); - return 0; - } + sql_row = mysql_fetch_row(sql_res); - sprintf(tmp_sql,"INSERT DELAYED INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')", - charlog_db, sd->account_id, RFIFOB(fd, 2), char_dat[0].name); - sql_query(tmp_sql,"char_select"); + if (sql_row) + mmo_char_fromsql(atoi(sql_row[0]), char_dat, 1); + else { + mysql_free_result(sql_res); + RFIFOSKIP(fd, 3); + break; + } - #ifdef DEBUG - printf("(\033[1;64m%d\033[0m) char selected (\033[1;32m%d\033[0m) \033[1;32m%s\033[0m" RETCODE, sd->account_id, RFIFOB(fd, 2), char_dat[0].name); - #endif + if (log_char) { + sprintf(tmp_sql,"INSERT INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')", + charlog_db, sd->account_id, RFIFOB(fd, 2), char_dat[0].name); + //query + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + } + printf("(\033[1;64m%d\033[0m) char selected (\033[1;32m%d\033[0m) \033[1;32m%s\033[0m" RETCODE, sd->account_id, RFIFOB(fd, 2), char_dat[0].name); + + i = search_mapserver(char_dat[0].last_point.map); + + // if map is not found, we check major cities + if (i < 0) { + if ((i = search_mapserver("prontera.gat")) >= 0) { // check is done without 'gat'. + memcpy(char_dat[0].last_point.map, "prontera.gat", 16); + char_dat[0].last_point.x = 273; // savepoint coordonates + char_dat[0].last_point.y = 354; + } else if ((i = search_mapserver("geffen.gat")) >= 0) { // check is done without 'gat'. + memcpy(char_dat[0].last_point.map, "geffen.gat", 16); + char_dat[0].last_point.x = 120; // savepoint coordonates + char_dat[0].last_point.y = 100; + } else if ((i = search_mapserver("morocc.gat")) >= 0) { // check is done without 'gat'. + memcpy(char_dat[0].last_point.map, "morocc.gat", 16); + char_dat[0].last_point.x = 160; // savepoint coordonates + char_dat[0].last_point.y = 94; + } else if ((i = search_mapserver("alberta.gat")) >= 0) { // check is done without 'gat'. + memcpy(char_dat[0].last_point.map, "alberta.gat", 16); + char_dat[0].last_point.x = 116; // savepoint coordonates + char_dat[0].last_point.y = 57; + } else if ((i = search_mapserver("payon.gat")) >= 0) { // check is done without 'gat'. + memcpy(char_dat[0].last_point.map, "payon.gat", 16); + char_dat[0].last_point.x = 87; // savepoint coordonates + char_dat[0].last_point.y = 117; + } else if ((i = search_mapserver("izlude.gat")) >= 0) { // check is done without 'gat'. + memcpy(char_dat[0].last_point.map, "izlude.gat", 16); + char_dat[0].last_point.x = 94; // savepoint coordonates + char_dat[0].last_point.y = 103; + } else { + int j; + // get first online server + i = 0; + for(j = 0; j < MAX_MAP_SERVERS; j++) + if (server_fd[j] >= 0 && server[j].map[0][0]) { + i = j; + printf("Map-server #%d found with a map: '%s'.\n", j, server[j].map[0]); + break; + } + // if no map-servers are connected, we send: server closed + if (j == MAX_MAP_SERVERS) { + WFIFOW(fd,0) = 0x81; + WFIFOL(fd,2) = 1; // 01 = Server closed + WFIFOSET(fd,3); + RFIFOSKIP(fd,3); + break; + } + } + } + WFIFOW(fd, 0) =0x71; + WFIFOL(fd, 2) =char_dat[0].char_id; + memcpy(WFIFOP(fd, 6), char_dat[0].last_point.map, 16); + //Lan check added by Kashy + if (lan_ip_check(p)) + WFIFOL(fd, 22) = inet_addr(lan_map_ip); + else + WFIFOL(fd, 22) = server[i].ip; + WFIFOW(fd, 26) = server[i].port; + WFIFOSET(fd, 28); + + if (auth_fifo_pos >= AUTH_FIFO_SIZE) { + auth_fifo_pos = 0; + } +// printf("auth_fifo set (auth_fifo_pos:%d) - account_id:%d char_id:%d login_id1:%d\n", auth_fifo_pos, sd->account_id, char_dat[0].char_id, sd->login_id1); + auth_fifo[auth_fifo_pos].account_id = sd->account_id; + auth_fifo[auth_fifo_pos].char_id = char_dat[0].char_id; + auth_fifo[auth_fifo_pos].login_id1 = sd->login_id1; + auth_fifo[auth_fifo_pos].login_id2 = sd->login_id2; + auth_fifo[auth_fifo_pos].delflag = 0; + //auth_fifo[auth_fifo_pos].char_pos = sd->found_char[ch]; + auth_fifo[auth_fifo_pos].char_pos = 0; + auth_fifo[auth_fifo_pos].sex = sd->sex; + auth_fifo[auth_fifo_pos].connect_until_time = sd->connect_until_time; + auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr; + auth_fifo_pos++; +// printf("0x66> end\n"); + RFIFOSKIP(fd, 3); + break; - i = search_mapserver(char_dat[0].last_point.map); - - // if map is not found, we check major cities - if (i < 0) { - if ((i = search_mapserver("prontera.gat")) >= 0) { // check is done without 'gat'. - memcpy(char_dat[0].last_point.map, "prontera.gat", 16); - char_dat[0].last_point.x = 273; // savepoint coordonates - char_dat[0].last_point.y = 354; - } else if ((i = search_mapserver("geffen.gat")) >= 0) { // check is done without 'gat'. - memcpy(char_dat[0].last_point.map, "geffen.gat", 16); - char_dat[0].last_point.x = 120; // savepoint coordonates - char_dat[0].last_point.y = 100; - } else if ((i = search_mapserver("morocc.gat")) >= 0) { // check is done without 'gat'. - memcpy(char_dat[0].last_point.map, "morocc.gat", 16); - char_dat[0].last_point.x = 160; // savepoint coordonates - char_dat[0].last_point.y = 94; - } else if ((i = search_mapserver("alberta.gat")) >= 0) { // check is done without 'gat'. - memcpy(char_dat[0].last_point.map, "alberta.gat", 16); - char_dat[0].last_point.x = 116; // savepoint coordonates - char_dat[0].last_point.y = 57; - } else if ((i = search_mapserver("payon.gat")) >= 0) { // check is done without 'gat'. - memcpy(char_dat[0].last_point.map, "payon.gat", 16); - char_dat[0].last_point.x = 87; // savepoint coordonates - char_dat[0].last_point.y = 117; - } else if ((i = search_mapserver("izlude.gat")) >= 0) { // check is done without 'gat'. - memcpy(char_dat[0].last_point.map, "izlude.gat", 16); - char_dat[0].last_point.x = 94; // savepoint coordonates - char_dat[0].last_point.y = 103; - } else { - int j; - // get first online server + case 0x67: // make new +// printf("0x67>request make new char\n"); + if (RFIFOREST(fd) < 37) + return 0; + i = make_new_char_sql(fd, RFIFOP(fd, 2)); + + //if (i < 0) { + // WFIFOW(fd, 0) = 0x6e; + // WFIFOB(fd, 2) = 0x00; + // WFIFOSET(fd, 3); + // RFIFOSKIP(fd, 37); + // break; + //} + //Changed that we can support 'Charname already exists' (-1) amd 'Char creation denied' (-2) + //And 'You are underaged' (-3) (XD) [Sirius] + if(i == -1){ + //already exists + WFIFOW(fd, 0) = 0x6e; + WFIFOB(fd, 2) = 0x00; + WFIFOSET(fd, 3); + RFIFOSKIP(fd, 37); + break; + }else if(i == -2){ + //denied + WFIFOW(fd, 0) = 0x6e; + WFIFOB(fd, 2) = 0x02; + WFIFOSET(fd, 3); + RFIFOSKIP(fd, 37); + break; + }else if(i == -3){ + //underaged XD + WFIFOW(fd, 0) = 0x6e; + WFIFOB(fd, 2) = 0x01; + WFIFOSET(fd, 3); + RFIFOSKIP(fd, 37); + break; + } + + WFIFOW(fd, 0) = 0x6d; + memset(WFIFOP(fd, 2), 0x00, 106); + + mmo_char_fromsql(i, char_dat, 0); i = 0; - for(j = 0; j < MAX_MAP_SERVERS && i < servers_connected; j++) - if (server_fd[j] >= 0 && server[j].map[0][0]) { - i = j; - printf("Map-server #%d found with a map: '%s'.\n", j, server[j].map[0]); + WFIFOL(fd, 2) = char_dat[i].char_id; + WFIFOL(fd,2+4) = char_dat[i].base_exp; + WFIFOL(fd,2+8) = char_dat[i].zeny; + WFIFOL(fd,2+12) = char_dat[i].job_exp; + WFIFOL(fd,2+16) = char_dat[i].job_level; + + WFIFOL(fd,2+28) = char_dat[i].karma; + WFIFOL(fd,2+32) = char_dat[i].manner; + + WFIFOW(fd,2+40) = 0x30; + WFIFOW(fd,2+42) = (char_dat[i].hp > 0x7fff) ? 0x7fff : char_dat[i].hp; + WFIFOW(fd,2+44) = (char_dat[i].max_hp > 0x7fff) ? 0x7fff : char_dat[i].max_hp; + WFIFOW(fd,2+46) = (char_dat[i].sp > 0x7fff) ? 0x7fff : char_dat[i].sp; + WFIFOW(fd,2+48) = (char_dat[i].max_sp > 0x7fff) ? 0x7fff : char_dat[i].max_sp; + WFIFOW(fd,2+50) = DEFAULT_WALK_SPEED; // char_dat[i].speed; + WFIFOW(fd,2+52) = char_dat[i].class_; + WFIFOW(fd,2+54) = char_dat[i].hair; + + WFIFOW(fd,2+58) = char_dat[i].base_level; + WFIFOW(fd,2+60) = char_dat[i].skill_point; + + WFIFOW(fd,2+64) = char_dat[i].shield; + WFIFOW(fd,2+66) = char_dat[i].head_top; + WFIFOW(fd,2+68) = char_dat[i].head_mid; + WFIFOW(fd,2+70) = char_dat[i].hair_color; + + memcpy(WFIFOP(fd,2+74), char_dat[i].name, 24); + + WFIFOB(fd,2+98) = char_dat[i].str; + WFIFOB(fd,2+99) = char_dat[i].agi; + WFIFOB(fd,2+100) = char_dat[i].vit; + WFIFOB(fd,2+101) = char_dat[i].int_; + WFIFOB(fd,2+102) = char_dat[i].dex; + WFIFOB(fd,2+103) = char_dat[i].luk; + WFIFOB(fd,2+104) = char_dat[i].char_num; + + WFIFOSET(fd, 108); + RFIFOSKIP(fd, 37); + //to do + for(ch = 0; ch < 9; ch++) { + if (sd->found_char[ch] == -1) { + sd->found_char[ch] = char_dat[i].char_id; break; } - // if no map-servers are connected, we send: server closed - if (j == MAX_MAP_SERVERS) { - WFIFOW(fd,0) = 0x81; - WFIFOL(fd,2) = 1; // 01 = Server closed - WFIFOSET(fd,3); - RFIFOSKIP(fd,3); - return 0; } - } - } - - WFIFOW(fd, 0) =0x71; - WFIFOL(fd, 2) =char_dat[0].char_id; - memcpy(WFIFOP(fd, 6), char_dat[0].last_point.map, 16); - - //Lan check added by Kashy - if (lan_ip_check(ip)) - WFIFOL(fd, 22) = inet_addr(lan_map_ip); - else - WFIFOL(fd, 22) = server[i].ip; - - WFIFOW(fd, 26) = server[i].port; - WFIFOSET(fd, 28); - if (auth_fifo_pos >= AUTH_FIFO_SIZE) - auth_fifo_pos = 0; - - #ifdef DEBUG - printf("auth_fifo set (auth_fifo_pos:%d) - account_id:%d char_id:%d login_id1:%d\n", auth_fifo_pos, sd->account_id, char_dat[0].char_id, sd->login_id1); - #endif - - auth_fifo[auth_fifo_pos].account_id = sd->account_id; - auth_fifo[auth_fifo_pos].char_id = char_dat[0].char_id; - auth_fifo[auth_fifo_pos].login_id1 = sd->login_id1; - auth_fifo[auth_fifo_pos].login_id2 = sd->login_id2; - auth_fifo[auth_fifo_pos].delflag = 0; - //auth_fifo[auth_fifo_pos].char_pos = sd->found_char[ch]; - auth_fifo[auth_fifo_pos].char_pos = 0; - auth_fifo[auth_fifo_pos].sex = sd->sex; - auth_fifo[auth_fifo_pos].connect_until_time = sd->connect_until_time; - auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr; - auth_fifo_pos++; + case 0x68: // delete + if (RFIFOREST(fd) < 46) + return 0; + printf("\033[1;31m Request Char Del:\033[0m \033[1;32m%d\033[0m(\033[1;32m%d\033[0m)\n", sd->account_id, RFIFOL(fd, 2)); + memcpy(email, RFIFOP(fd,6), 40); + sprintf(tmp_sql, "SELECT `email` FROM `%s` WHERE `%s`='%d'",login_db, login_db_account_id, sd->account_id); + if (mysql_query(&lmysql_handle, tmp_sql)) { + printf("\033[1;31m DB server Error Delete Char data - %s \033[0m \n", mysql_error(&lmysql_handle)); + } + sql_res = mysql_store_result(&lmysql_handle); + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); + + if ( (strcmp(email,sql_row[0]) == 0) || // client_value == db_value? + ((strcmp(email,"") == 0) && + (strcmp(sql_row[0],"a@a.com") == 0)) ) { // client_value == "" && db_value == "a@a.com" ? + mysql_free_result(sql_res); + } else { + WFIFOW(fd, 0) = 0x70; + WFIFOB(fd, 2) = 0; + WFIFOSET(fd, 3); + RFIFOSKIP(fd, 46); + mysql_free_result(sql_res); + break; + } + } else { + WFIFOW(fd, 0) = 0x70; + WFIFOB(fd, 2) = 0; + WFIFOSET(fd, 3); + RFIFOSKIP(fd, 46); + mysql_free_result(sql_res); + break; + } + sprintf(tmp_sql, "SELECT `name`,`partner_id` FROM `%s` WHERE `char_id`='%d'",char_db, RFIFOL(fd,2)); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + if(sql_res) + sql_row = mysql_fetch_row(sql_res); + + if (sql_res && sql_row[0]) { + //delete char from SQL + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",pet_db, RFIFOL(fd, 2)); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",inventory_db, RFIFOL(fd, 2)); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } -// printf("0x66> end\n"); + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",cart_db, RFIFOL(fd, 2)); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } - RFIFOSKIP(fd, 3); + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",memo_db, RFIFOL(fd, 2)); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } - return 0; -} + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",skill_db, RFIFOL(fd, 2)); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } -int make_new_char(int fd, int len) { - if (len < 37) - return -1; + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",char_db, RFIFOL(fd, 2)); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } - int i, ch; - struct char_session_data *sd = session[fd]->session_data; + //Divorce [Wizputer] + if (sql_row[1] != 0) { + unsigned char buf[64]; + sprintf(tmp_sql,"UPDATE `%s` SET `partner_id`='0' WHERE `char_id`='%d'",char_db,atoi(sql_row[1])); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sprintf(tmp_sql,"DELETE FROM `%s` WHERE (`nameid`='%d' OR `nameid`='%d') AND `char_id`='%d'",inventory_db,WEDDING_RING_M,WEDDING_RING_F,atoi(sql_row[1])); + if(mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + WBUFW(buf,0) = 0x2b12; + WBUFL(buf,2) = atoi(sql_row[0]); + WBUFL(buf,6) = atoi(sql_row[1]); + mapif_sendall(buf,10); + } + // Also delete info from guildtables. + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",guild_member_db, RFIFOL(fd,2)); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } - #ifdef DEBUG - printf("Request to make a new char\n"); - #endif + sprintf(tmp_sql, "SELECT `guild_id` FROM `%s` WHERE `master` = '%s'", guild_db, sql_row[0]); - i = make_new_char_sql(fd, RFIFOP(fd, 2)); + if (mysql_query(&mysql_handle, tmp_sql) == 0) { + sql_res = mysql_store_result(&mysql_handle); - if (i < 0) { - WFIFOW(fd, 0) = 0x6e; - WFIFOB(fd, 2) = 0x00; - WFIFOSET(fd, 3); - RFIFOSKIP(fd, 37); - return 0; - } + if (sql_res != NULL) { + if (mysql_num_rows(sql_res) != 0) { + sql_row = mysql_fetch_row(sql_res); - WFIFOW(fd, 0) = 0x6d; - memset(WFIFOP(fd, 2), 0x00, 106); + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_db, atoi(sql_row[0])); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } - mmo_char_fromsql(i, char_dat, 0); + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_member_db, atoi(sql_row[0])); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } - i = 0; + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_castle_db, atoi(sql_row[0])); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } - WFIFOL(fd, 2) = char_dat[i].char_id; - WFIFOL(fd,2+4) = char_dat[i].base_exp; - WFIFOL(fd,2+8) = char_dat[i].zeny; - WFIFOL(fd,2+12) = char_dat[i].job_exp; - WFIFOL(fd,2+16) = char_dat[i].job_level; - WFIFOL(fd,2+28) = char_dat[i].karma; - WFIFOL(fd,2+32) = char_dat[i].manner; - WFIFOW(fd,2+40) = 0x30; - WFIFOW(fd,2+42) = (char_dat[i].hp > 0x7fff) ? 0x7fff : char_dat[i].hp; - WFIFOW(fd,2+44) = (char_dat[i].max_hp > 0x7fff) ? 0x7fff : char_dat[i].max_hp; - WFIFOW(fd,2+46) = (char_dat[i].sp > 0x7fff) ? 0x7fff : char_dat[i].sp; - WFIFOW(fd,2+48) = (char_dat[i].max_sp > 0x7fff) ? 0x7fff : char_dat[i].max_sp; - WFIFOW(fd,2+50) = DEFAULT_WALK_SPEED; // char_dat[i].speed; - WFIFOW(fd,2+52) = char_dat[i].class; - WFIFOW(fd,2+54) = char_dat[i].hair; - WFIFOW(fd,2+58) = char_dat[i].base_level; - WFIFOW(fd,2+60) = char_dat[i].skill_point; - WFIFOW(fd,2+64) = char_dat[i].shield; - WFIFOW(fd,2+66) = char_dat[i].head_top; - WFIFOW(fd,2+68) = char_dat[i].head_mid; - WFIFOW(fd,2+70) = char_dat[i].hair_color; - memcpy(WFIFOP(fd,2+74), char_dat[i].name, 24); - WFIFOB(fd,2+98) = char_dat[i].str; - WFIFOB(fd,2+99) = char_dat[i].agi; - WFIFOB(fd,2+100) = char_dat[i].vit; - WFIFOB(fd,2+101) = char_dat[i].int_; - WFIFOB(fd,2+102) = char_dat[i].dex; - WFIFOB(fd,2+103) = char_dat[i].luk; - WFIFOB(fd,2+104) = char_dat[i].char_num; - WFIFOSET(fd, 108); - - RFIFOSKIP(fd, 37); - - //to do - for(ch = 0; ch < 9; ch++) { - if (sd->found_char[ch] == -1) { - sd->found_char[ch] = char_dat[i].char_id; - break; - } - } + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_storage_db, atoi(sql_row[0])); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } - return 0; -} + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d' OR `alliance_id` = '%d'", guild_alliance_db, atoi(sql_row[0]), atoi(sql_row[0])); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } -int delete_char(int fd, int len) { - if (len < 46) - return -1; + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_position_db, atoi(sql_row[0])); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } - char email[40]; - int char_id = RFIFOL(fd, 2); - struct char_session_data *sd = session[fd]->session_data; + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_skill_db, atoi(sql_row[0])); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } - #ifdef DEBUG - printf("\033[1;31m Request Char Del:\033[0m \033[1;32m%d\033[0m(\033[1;32m%d\033[0m)\n", sd->account_id, char_id); - #endif + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_expulsion_db, atoi(sql_row[0])); + if (mysql_query(&mysql_handle, tmp_sql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } - memcpy(email, RFIFOP(fd,6), 40); - sprintf(tmp_sql, "SELECT `email` FROM `%s` WHERE `%s`='%d'",login_db, login_db_account_id, sd->account_id); - sql_query(tmp_sql,"delete_char"); + mysql_free_result(sql_res); + } + } else { + if (mysql_errno(&mysql_handle) != 0) { + printf("Database server error: %s\n", mysql_error(&mysql_handle)); + } + } + } else { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + } - if ((sql_res = mysql_store_result(&mysql_handle)) &&(sql_row = mysql_fetch_row(sql_res))) { - if (strcmp(email,sql_row[0]) == 0) { - mysql_free_result(sql_res); - } else { - WFIFOW(fd, 0) = 0x70; - WFIFOB(fd, 2) = 0; - WFIFOSET(fd, 3); + for(i = 0; i < 9; i++) { + printf("char comp: %d - %d (%d)\n", sd->found_char[i], RFIFOL(fd, 2), sd->account_id); + if (sd->found_char[i] == RFIFOL(fd, 2)) { + for(ch = i; ch < 9-1; ch++) + sd->found_char[ch] = sd->found_char[ch+1]; + sd->found_char[8] = -1; + break; + } + } + if (i == 9) { // reject + WFIFOW(fd, 0) = 0x70; + WFIFOB(fd, 2) = 0; + WFIFOSET(fd, 3); + } else { // deleted! + WFIFOW(fd, 0) = 0x6f; + WFIFOSET(fd, 2); + } RFIFOSKIP(fd, 46); - mysql_free_result(sql_res); - return 0; - } - } else { - WFIFOW(fd, 0) = 0x70; - WFIFOB(fd, 2) = 0; - WFIFOSET(fd, 3); - RFIFOSKIP(fd, 46); - mysql_free_result(sql_res); - return 0; - } - - sprintf(tmp_sql, "SELECT `partner_id` FROM `%s` WHERE `char_id`='%d'",char_db, char_id); - sql_query(tmp_sql,"delete_char"); - - if ((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) { - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",char_db, char_id); - sql_query(tmp_sql,"delete_char"); - - if (sql_row[0] != 0) { - char buf[16]; - WBUFW(buf,0) = 0x2b12; - WBUFL(buf,2) = char_id; - WBUFL(buf,6) = atoi(sql_row[1]); - mapif_sendall(buf,10); - } - } - - mysql_free_result(sql_res); - - WFIFOW(fd, 0) = 0x6f; - WFIFOSET(fd, 2); - - RFIFOSKIP(fd, 46); - - return 0; -} - -int mapserver_login(int fd, int len) { - if (len < 60) - return -1; - - int i; - - WFIFOW(fd, 0) = 0x2af9; - - for(i = 0; i < MAX_MAP_SERVERS; i++) { - if (server_fd[i] < 0) break; - } - - if (i == MAX_MAP_SERVERS || strcmp(RFIFOP(fd,2), userid) || strcmp(RFIFOP(fd,26), passwd)) { - WFIFOB(fd,2) = 3; - WFIFOSET(fd, 3); - } else { - WFIFOB(fd,2) = 0; - WFIFOSET(fd, 3); - session[fd]->func_parse = parse_frommap; - server_fd[i] = fd; - if(anti_freeze_enable) - server_freezeflag[i] = 5; // Map anti-freeze system. Counter. 5 ok, 4...0 freezed - server[i].ip = RFIFOL(fd, 54); - server[i].port = RFIFOW(fd, 58); - server[i].users = 0; - memset(server[i].map, 0, sizeof(server[i].map)); - realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - char_mapif_init(fd); - } - - RFIFOSKIP(fd,60); - - return 0; -} - -int skip_packet(int fd, int len, int real_len) { - if (len < real_len) - return 0; - - RFIFOSKIP(fd,real_len); - - return 0; -} -int get_info(int fd, int len) { - // Athena info get - WFIFOW(fd, 0) = 0x7531; - WFIFOB(fd, 2) = ATHENA_MAJOR_VERSION; - WFIFOB(fd, 3) = ATHENA_MINOR_VERSION; - WFIFOB(fd, 4) = ATHENA_REVISION; - WFIFOB(fd, 5) = ATHENA_RELEASE_FLAG; - WFIFOB(fd, 6) = ATHENA_OFFICIAL_FLAG; - WFIFOB(fd, 7) = ATHENA_SERVER_INTER | ATHENA_SERVER_CHAR; - WFIFOW(fd, 8) = ATHENA_MOD_VERSION; - WFIFOSET(fd, 10); - RFIFOSKIP(fd, 2); - - return 0; -} - -int parse_char(int fd) { - int len,res=0; - unsigned short cmd; - unsigned char *ip = (unsigned char *) &session[fd]->client_addr.sin_addr; - struct char_session_data *sd = session[fd]->session_data; - - if(login_fd < 0) - session[fd]->eof = 1; - - if(session[fd]->eof) { - if (fd == login_fd) - login_fd = -1; - close(fd); - delete_session(fd); - return 0; - } - - len = RFIFOREST(fd); - - while(len >= 2 && res == 0) { - - cmd = RFIFOW(fd,0); - - // crc32‚̃XƒLƒbƒv—p - if( sd==NULL && // –¢ƒƒOƒCƒ“orŠÇ—ƒpƒPƒbƒg - RFIFOREST(fd)>=4 && // Å’áƒoƒCƒg”§ŒÀ • 0x7530,0x7532ŠÇ—ƒpƒPœ‹Ž - RFIFOREST(fd)<=21 && // Å‘åƒoƒCƒg”§ŒÀ • ƒT[ƒo[ƒƒOƒCƒ“œ‹Ž - cmd!=0x20b && // md5’Ê’mƒpƒPƒbƒgœ‹Ž - (RFIFOREST(fd)<6 || RFIFOW(fd,4)==0x65) ){ // ŽŸ‚ɉ½‚©ƒpƒPƒbƒg‚ª—ˆ‚Ä‚é‚È‚çAÚ‘±‚łȂ¢‚Æ‚¾‚ß - RFIFOSKIP(fd,4); - cmd = RFIFOW(fd,0); - printf("parse_char : %d crc32 skipped\n",fd); - if(RFIFOREST(fd)==0) + case 0x2af8: // login as map-server + if (RFIFOREST(fd) < 60) return 0; - } - -// if(cmd<30000 && cmd!=0x187) -// printf("parse_char : %d %d %d\n",fd,RFIFOREST(fd),cmd); - - // •s³ƒpƒPƒbƒg‚̈— -// if (sd == NULL && cmd != 0x65 && cmd != 0x20b && cmd != 0x187 && -// cmd != 0x2af8 && cmd != 0x7530 && cmd != 0x7532) -// cmd = 0xffff; // ƒpƒPƒbƒgƒ_ƒ“ƒv‚ð•\ަ‚³‚¹‚é + WFIFOW(fd, 0) = 0x2af9; + for(i = 0; i < MAX_MAP_SERVERS; i++) { + if (server_fd[i] < 0) + break; + } + if (i == MAX_MAP_SERVERS || strcmp((const char*)RFIFOP(fd,2), userid) || strcmp((const char*)RFIFOP(fd,26), passwd)) { + WFIFOB(fd,2) = 3; + WFIFOSET(fd, 3); + } else { +// int len; + WFIFOB(fd,2) = 0; + WFIFOSET(fd, 3); + session[fd]->func_parse = parse_frommap; + server_fd[i] = fd; + server[i].ip = RFIFOL(fd, 54); + server[i].port = RFIFOW(fd, 58); + server[i].users = 0; + memset(server[i].map, 0, sizeof(server[i].map)); + realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); + char_mapif_init(fd); + // send gm acccounts level to map-servers +/* removed by CLOWNISIUS due to isGM + len = 4; + WFIFOW(fd,0) = 0x2b15; + for(i = 0; i < GM_num; i++) { + WFIFOL(fd,len) = gm_account[i].account_id; + WFIFOB(fd,len+4) = (unsigned char)gm_account[i].level; + len += 5; + } + WFIFOW(fd,2) = len; + WFIFOSET(fd,len);*/ + } + RFIFOSKIP(fd,60); + break; - switch(cmd){ - //20040622 encryption ragexe correspondence - case 0x20b: res = skip_packet(fd,len,19); break; + case 0x187: // Alive? + if (RFIFOREST(fd) < 6) { + return 0; + } + RFIFOSKIP(fd, 6); + break; - case 0x65: res = client_request_connect(fd,len); break; - case 0x66: res = char_select(fd,len,ip); break; - case 0x67: res = make_new_char(fd,len); break; - case 0x68: res = delete_char(fd,len); break; - case 0x2af8: res = mapserver_login(fd,len); break; - case 0x187: res = skip_packet(fd,len,6); break; - case 0x7530: res = get_info(fd,len); break; + case 0x7530: // Athena info get + WFIFOW(fd, 0) = 0x7531; + WFIFOB(fd, 2) = ATHENA_MAJOR_VERSION; + WFIFOB(fd, 3) = ATHENA_MINOR_VERSION; + WFIFOB(fd, 4) = ATHENA_REVISION; + WFIFOB(fd, 5) = ATHENA_RELEASE_FLAG; + WFIFOB(fd, 6) = ATHENA_OFFICIAL_FLAG; + WFIFOB(fd, 7) = ATHENA_SERVER_INTER | ATHENA_SERVER_CHAR; + WFIFOW(fd, 8) = ATHENA_MOD_VERSION; + WFIFOSET(fd, 10); + RFIFOSKIP(fd, 2); + return 0; case 0x7532: // disconnect(default also disconnect) default: session[fd]->eof = 1; return 0; } - - len = RFIFOREST(fd); } RFIFOFLUSH(fd); @@ -2586,8 +2935,8 @@ int parse_char(int fd) { int parse_console(char *buf) { char *type,*command; - type = (char *)malloc(64); - command = (char *)malloc(64); + type = (char *)aMalloc(64); + command = (char *)aMalloc(64); memset(type,0,64); memset(command,0,64); @@ -2599,9 +2948,9 @@ int parse_console(char *buf) { printf("Type of command: %s || Command: %s \n",type,command); - if(buf) free(buf); - if(type) free(type); - if(command) free(command); + if(buf) aFree(buf); + if(type) aFree(type); + if(command) aFree(command); return 0; } @@ -2612,7 +2961,7 @@ int mapif_sendall(unsigned char *buf, unsigned int len) { int fd; c = 0; - for(i = 0; i < MAX_MAP_SERVERS && i < servers_connected; i++) { + for(i = 0; i < MAX_MAP_SERVERS; i++) { if ((fd = server_fd[i]) >= 0) { memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); @@ -2628,7 +2977,7 @@ int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len) { int fd; c = 0; - for(i=0, c=0;i<MAX_MAP_SERVERS && i < servers_connected;i++){ + for(i=0, c=0;i<MAX_MAP_SERVERS;i++){ if ((fd = server_fd[i]) >= 0 && fd != sfd) { memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd, len); @@ -2643,7 +2992,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len) { int i; if (fd >= 0) { - for(i = 0; i < MAX_MAP_SERVERS && i < servers_connected; i++) { + for(i = 0; i < MAX_MAP_SERVERS; i++) { if (fd == server_fd[i]) { memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); @@ -2654,6 +3003,24 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len) { return 0; } +int send_users_tologin(int tid, unsigned int tick, int id, int data) { + int users = count_users(); + unsigned char buf[16]; + + if (login_fd > 0 && session[login_fd]) { + // send number of user to login server + WFIFOW(login_fd,0) = 0x2714; + WFIFOL(login_fd,2) = users; + WFIFOSET(login_fd,6); + } + // send number of players to all map-servers + WBUFW(buf,0) = 0x2b00; + WBUFL(buf,2) = users; + mapif_sendall(buf, 6); + + return 0; +} + int check_connect_login_server(int tid, unsigned int tick, int id, int data) { if (login_fd <= 0 || session[login_fd] == NULL) { printf("Attempt to connect to login-server...\n"); @@ -2737,33 +3104,48 @@ int char_lan_config_read(const char *lancfgName){ return 0; } +static int char_db_final(void *key,void *data,va_list ap) +{ + struct mmo_charstatus *p = (struct mmo_charstatus *) data; + if (p) aFree(p); + return 0; +} void do_final(void) { - printf("Closing char-server...\n"); - + printf("Doing final stage...\n"); + //mmo_char_sync(); + //inter_save(); do_final_itemdb(); - //check SQL save progress. //wait until save char complete - printf("Waiting until char saving complete...\n"); - do { - sleep (0); - }while (save_flag != 0); - sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `online`='1'", char_db); - sql_query(tmp_sql,"do_final"); + set_all_offline(); + + flush_fifos(); sprintf(tmp_sql,"DELETE FROM `ragsrvinfo"); - sql_query(tmp_sql,"do_final"); + if (mysql_query(&mysql_handle, tmp_sql)) + printf("DB server Error (insert `char`)- %s\n", mysql_error(&mysql_handle)); + + if(gm_account) { + aFree(gm_account); + gm_account = 0; + } - if(gm_account) free(gm_account); + if(char_dat) { + aFree(char_dat); + char_dat = 0; + } - if(char_dat) free(char_dat); delete_session(login_fd); delete_session(char_fd); + numdb_final(char_db_, char_db_final); + exit_dbn(); mysql_close(&mysql_handle); + mysql_close(&lmysql_handle); + timer_final(); - printf("Good-bye...\n"); + printf("ok! all done...\n"); } void sql_config_read(const char *cfgName){ /* Kalaspuff, to get login_db */ @@ -2828,11 +3210,7 @@ void sql_config_read(const char *cfgName){ /* Kalaspuff, to get login_db */ strcpy(db_path,w2); //Map server option to use SQL db or not }else if(strcmpi(w1,"use_sql_db")==0){ // added for sql item_db read for char server [Valaris] - if (strcmpi(w2, "yes")) { - db_use_sqldbs = 1; - } else if (strcmpi(w2, "no")) { - db_use_sqldbs = 0; - } + db_use_sqldbs = config_switch(w2); printf("Using SQL dbs: %s\n",w2); //custom columns for login database }else if(strcmpi(w1,"login_db_level")==0){ @@ -2846,6 +3224,7 @@ void sql_config_read(const char *cfgName){ /* Kalaspuff, to get login_db */ }else if(strcmpi(w1,"import")==0){ sql_config_read(w2); } + } fclose(fp); printf("reading configure done.....\n"); @@ -2869,15 +3248,15 @@ int char_config_read(const char *cfgName) { if (sscanf(line,"%[^:]: %[^\r\n]", w1, w2) != 2) continue; - remove_control_chars(w1); - remove_control_chars(w2); + remove_control_chars((unsigned char *) w1); + remove_control_chars((unsigned char *) w2); if (strcmpi(w1, "userid") == 0) { memcpy(userid, w2, 24); } else if (strcmpi(w1, "passwd") == 0) { memcpy(passwd, w2, 24); } else if (strcmpi(w1, "server_name") == 0) { memcpy(server_name, w2, 16); - printf("%s server has been intialized\n", w2); + printf("%s server has been initialized\n", w2); } else if (strcmpi(w1, "wisp_server_name") == 0) { if (strlen(w2) >= 4) { memcpy(wisp_server_name, w2, sizeof(wisp_server_name)); @@ -2901,6 +3280,14 @@ int char_config_read(const char *cfgName) { sprintf(char_ip_str, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); } else memcpy(char_ip_str, w2, 16); + } else if (strcmpi(w1, "bind_ip") == 0) { + bind_ip_set_ = 1; + h = gethostbyname (w2); + if(h != NULL) { + printf("Character server binding IP address : %s -> %d.%d.%d.%d\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + sprintf(bind_ip_str, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + } else + memcpy(bind_ip_str, w2, 16); } else if (strcmpi(w1, "char_port") == 0) { char_port = atoi(w2); } else if (strcmpi(w1, "char_maintenance") == 0) { @@ -2911,6 +3298,10 @@ int char_config_read(const char *cfgName) { max_connect_user = atoi(w2); if (max_connect_user < 0) max_connect_user = 0; // unlimited online players + } else if(strcmpi(w1, "gm_allow_level") == 0) { + gm_allow_level = atoi(w2); + if(gm_allow_level < 0) + gm_allow_level = 99; } else if (strcmpi(w1, "check_ip_flag") == 0) { check_ip_flag = config_switch(w2); } else if (strcmpi(w1, "autosave_time") == 0) { @@ -2960,13 +3351,8 @@ int char_config_read(const char *cfgName) { strcpy(char_name_letters, w2); } else if (strcmpi(w1, "check_ip_flag") == 0) { check_ip_flag = config_switch(w2); - // anti-freeze options [Valaris] - } else if(strcmpi(w1,"anti_freeze_enable")==0){ - anti_freeze_enable = config_switch(w2); - } else if (strcmpi(w1, "anti_freeze_interval") == 0) { - ANTI_FREEZE_INTERVAL = atoi(w2); - if (ANTI_FREEZE_INTERVAL < 5) - ANTI_FREEZE_INTERVAL = 5; // minimum 5 seconds + } else if (strcmpi(w1, "chars_per_account") == 0) { //maxchars per account [Sirius] + char_per_account = atoi(w2); } else if (strcmpi(w1, "import") == 0) { char_config_read(w2); } else if (strcmpi(w1, "console") == 0) { @@ -2976,9 +3362,6 @@ int char_config_read(const char *cfgName) { } fclose(fp); -//Read ItemDB - do_init_itemdb(); - return 0; } @@ -3004,6 +3387,7 @@ int flush_timer(int tid, unsigned int tick, int id, int data){ int do_init(int argc, char **argv){ int i; + SERVER_TYPE = SERVER_CHAR; for(i = 0; i < MAX_MAP_SERVERS; i++) { memset(&server[i], 0, sizeof(struct mmo_map_server)); server_fd[i] = -1; @@ -3018,6 +3402,9 @@ int do_init(int argc, char **argv){ inter_init((argc > 2) ? argv[2] : inter_cfgName); // inter server ÃʱâÈ printf("interserver configuration reading done.....\n"); + //Read ItemDB + do_init_itemdb(); + printf("start char server initializing.....\n"); mmo_char_sql_init(); printf("char server initializing done.....\n"); @@ -3028,16 +3415,13 @@ int do_init(int argc, char **argv){ printf("set terminate function -> do_final().....\n"); set_termfunc(do_final); - printf("open port %d.....\n",char_port); - char_fd = make_listen_port(char_port); - if ((naddr_ != 0) && (login_ip_set_ == 0 || char_ip_set_ == 0)) { // The char server should know what IP address it is running on // - MouseJstr int localaddr = ntohl(addr_[0]); unsigned char *ptr = (unsigned char *) &localaddr; char buf[16]; - sprintf(buf, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);; + sprintf(buf, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]); if (naddr_ != 1) printf("Multiple interfaces detected.. using %s as our IP address\n", buf); else @@ -3048,21 +3432,31 @@ int do_init(int argc, char **argv){ strcpy(char_ip_str, buf); if (ptr[0] == 192 && ptr[1] == 168) - printf("Firewall detected.. edit lan_support.conf and char_athena.conf"); + printf("Firewall detected.. edit lan_support.conf and char_athena.conf\n"); } login_ip = inet_addr(login_ip_str); char_ip = inet_addr(char_ip_str); + printf("open port %d.....\n",char_port); + //char_fd = make_listen_port(char_port); + if (bind_ip_set_) + char_fd = make_listen_bind(inet_addr(bind_ip_str),char_port); + else + char_fd = make_listen_bind(INADDR_ANY,char_port); + // send ALIVE PING to login server. printf("add interval tic (check_connect_login_server)....\n"); i = add_timer_interval(gettick() + 10, check_connect_login_server, 0, 0, 10 * 1000); + // send USER COUNT PING to login server. + printf("add interval tic (send_users_tologin)....\n"); + i = add_timer_interval(gettick() + 10, send_users_tologin, 0, 0, 5 * 1000); + //no need to set sync timer on SQL version. //printf("add interval tic (mmo_char_sync_timer)....\n"); //i = add_timer_interval(gettick() + 10, mmo_char_sync_timer, 0, 0, autosave_interval); - add_timer_func_list(map_anti_freeze_system, "map_anti_freeze_system"); //Added for Mugendais I'm Alive mod if(imalive_on) add_timer_interval(gettick()+10, imalive_timer,0,0,imalive_time*1000); @@ -3071,27 +3465,114 @@ int do_init(int argc, char **argv){ if(flush_on) add_timer_interval(gettick()+10, flush_timer,0,0,flush_time); - if(anti_freeze_enable > 0) { - add_timer_func_list(map_anti_freeze_system, "map_anti_freeze_system"); - i = add_timer_interval(gettick() + 1000, map_anti_freeze_system, 0, 0, ANTI_FREEZE_INTERVAL * 1000); // checks every X seconds user specifies - } + read_gm_account(); if ( console ) { set_defaultconsoleparse(parse_console); start_console(); } + //Cleaning the tables for NULL entrys @ startup [Sirius] + //Chardb clean + printf("Cleaning the '%s' table...", char_db); + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `account_id` = '0'", char_db); + if(mysql_query(&mysql_handle, tmp_sql)){ + //error on clean + printf(" fail.\n"); + }else{ + printf(" done.\n"); + } + + //guilddb clean + printf("Cleaning the '%s' table...", guild_db); + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_lv` = '0' AND `max_member` = '0' AND `exp` = '0' AND `next_exp` = '0' AND `average_lv` = '0'", guild_db); + if(mysql_query(&mysql_handle, tmp_sql)){ + //error on clean + printf(" fail.\n"); + }else{ + printf(" done.\n"); + } + + //guildmemberdb clean + printf("Cleaning the '%s' table...", guild_member_db); + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '0' AND `account_id` = '0' AND `char_id` = '0'", guild_member_db); + if(mysql_query(&mysql_handle, tmp_sql)){ + //error on clean + printf(" fail.\n"); + }else{ + printf(" done.\n"); + } + + + printf("char server init func end (now unlimited loop start!)....\n"); printf("The char-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n", char_port); return 0; } - #undef mysql_query -int STDCALL mysql_query(MYSQL *mysql, const char *q); int debug_mysql_query(char *file, int line, void *mysql, const char *q) { +#ifdef TWILIGHT printf("sql: %s:%d# %s\n", file, line, q); +#endif return mysql_query((MYSQL *) mysql, q); } +int char_child(int parent_id, int child_id) { + int tmp_id = 0; + sprintf (tmp_sql, "SELECT `child` FROM `%s` WHERE `char_id` = '%d'", char_db, parent_id); + if (mysql_query (&mysql_handle, tmp_sql)) { + printf ("DB server Error (select `char2`)- %s\n", mysql_error (&mysql_handle)); + } + sql_res = mysql_store_result (&mysql_handle); + if (sql_res) { + sql_row = mysql_fetch_row (sql_res); + tmp_id = atoi (sql_row[0]); + mysql_free_result (sql_res); + } + else + printf("CHAR: child Failed!\n"); + if ( tmp_id == child_id ) + return 1; + else + return 0; +} + +int char_married(int pl1,int pl2) { + int tmp_id = 0; + sprintf (tmp_sql, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", char_db, pl1); + if (mysql_query (&mysql_handle, tmp_sql)) { + printf ("DB server Error (select `char2`)- %s\n", mysql_error (&mysql_handle)); + } + sql_res = mysql_store_result (&mysql_handle); + if (sql_res) { + sql_row = mysql_fetch_row (sql_res); + tmp_id = atoi (sql_row[0]); + mysql_free_result (sql_res); + } + else + printf("CHAR: married Failed!\n"); + if ( tmp_id == pl2 ) + return 1; + else + return 0; +} + +int char_nick2id (char *name) { + int char_id = 0; + sprintf (tmp_sql, "SELECT `char_id` FROM `%s` WHERE `name` = '%s'", char_db, name); + if (mysql_query (&mysql_handle, tmp_sql)) { + printf ("DB server Error (select `char2`)- %s\n", mysql_error (&mysql_handle)); + } + sql_res = mysql_store_result (&mysql_handle); + if (sql_res) { + sql_row = mysql_fetch_row (sql_res); + char_id = atoi (sql_row[0]); + mysql_free_result (sql_res); + } + else + printf ("CHAR: nick2id Failed!\n"); + return char_id; +} + diff --git a/src/char_sql/char.h b/src/char_sql/char.h index 8da399eff..6ade96c36 100644 --- a/src/char_sql/char.h +++ b/src/char_sql/char.h @@ -40,12 +40,15 @@ enum { struct itemtemp{ struct itemtmp equip[MAX_GUILD_STORAGE],notequip[MAX_GUILD_STORAGE]; }; -int memitemdata_to_sql(struct itemtemp mapitem, int eqcount, int noteqcount, int char_id,int tableswitch); -int memitemdata_to_sql2(struct itemtemp mapitem, int eqcount, int char_id,int tableswitch); +int memitemdata_to_sql(struct itemtmp mapitem[], int count, int char_id,int tableswitch); int mapif_sendall(unsigned char *buf,unsigned int len); int mapif_sendallwos(int fd,unsigned char *buf,unsigned int len); int mapif_send(int fd,unsigned char *buf,unsigned int len); +int char_nick2id (char *name); +int char_married(int pl1,int pl2); +int char_child(int parent_id, int child_id); + extern int autosave_interval; extern char db_path[]; extern char char_db[256]; @@ -68,11 +71,13 @@ extern char guild_storage_db[256]; extern char party_db[256]; extern char pet_db[256]; -int db_use_sqldbs; // added for sql item_db read for char server [Valaris] +extern int db_use_sqldbs; // added for sql item_db read for char server [Valaris] extern char login_db_level[32]; extern char login_db_account_id[32]; extern int lowest_gm_level; +extern int GM_num; +extern struct gm_account *gm_account; extern int debug_mysql_query(char *file, int line, void *mysql, const char *q); diff --git a/src/char_sql/int_guild.c b/src/char_sql/int_guild.c index a850bc0f5..794f2e01f 100644 --- a/src/char_sql/int_guild.c +++ b/src/char_sql/int_guild.c @@ -3,8 +3,12 @@ // SQL conversion by hack // +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + #include "char.h" -#include "strlib.h" +#include "../common/strlib.h" #include "int_storage.h" #include "inter.h" #include "int_guild.h" @@ -12,17 +16,10 @@ #include "mmo.h" #include "socket.h" #include "db.h" -#include "utils.h" - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> +#include "malloc.h" static struct dbt *guild_db_; static struct dbt *castle_db_; -static struct dbt *guild_expcache_db_; -static struct dbt *guild_infoevent_db_; -static struct dbt *guild_castleinfoevent_db_; static struct guild *guild_pt; static struct guild *guild_pt2; @@ -39,6 +36,18 @@ int mapif_guild_basicinfochanged(int guild_id,int type,const void *data,int len) int mapif_guild_info(int fd,struct guild *g); int guild_break_sub(void *key,void *data,va_list ap); +#define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y) + +static int _erase_guild(void *key, void *data, va_list ap) { + int guild = va_arg(ap, int); + struct guild_castle * castle = (struct guild_castle *) data; + if (castle->guild_id == guild) { + aFree(castle); + db_erase(castle_db_, key); + } + + return 0; +} // Save guild into sql int inter_guild_tosql(struct guild *g,int flag) @@ -47,67 +56,114 @@ int inter_guild_tosql(struct guild *g,int flag) // 2 `guild_member` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`rsv1`,`rsv2`,`name`) // 4 `guild_position` (`guild_id`,`position`,`name`,`mode`,`exp_mode`) // 8 `guild_alliance` (`guild_id`,`opposition`,`alliance_id`,`name`) - // 16 `guild_expulsion` (`guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3`) + // 16 `guild_expulsion` (`guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3`) // 32 `guild_skill` (`guild_id`,`id`,`lv`) - - char t_name[100],t_master[24],t_mes1[60],t_mes2[120],t_member[24],t_position[24],t_alliance[24]; // temporay storage for str convertion; + + char t_name[100],t_master[24],t_mes1[60],t_mes2[240],t_member[24],t_position[24],t_alliance[24]; // temporay storage for str convertion; char t_ename[24],t_emes[40]; char emblem_data[4096]; - int first = 1, i=0; - int guild_member=0,guild_online_member=0; - struct StringBuf sbuf; + int i=0; + int guild_exist=0,guild_member=0,guild_online_member=0; - StringBuf_Init(&sbuf); - if (g->guild_id<=0) return -1; - - printf("(\033[1;35m%d\033[0m) Request save guild - ",g->guild_id); - + + printf("(\033[1;35m%d\033[0m) Request save guild -(flag 0x%x) ",g->guild_id, flag); + jstrescapecpy(t_name, g->name); - - guild_member = 0; - i = 0; - while (i<g->max_member) { - if (g->member[i].account_id>0) guild_member++; - i++; + + //printf("- Check if guild %d exists\n",g->guild_id); + sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `guild_id`='%d'",guild_db,g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (delete `guild`)- %s\n", mysql_error(&mysql_handle) ); + } + sql_res = mysql_store_result(&mysql_handle) ; + if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { + sql_row = mysql_fetch_row(sql_res); + guild_exist = atoi (sql_row[0]); + //printf("- Check if guild %d exists : %s\n",g->guild_id,((guild_exist==0)?"No":"Yes")); + } + mysql_free_result(sql_res) ; //resource free + + if (guild_exist >0){ + // Check members in party + sprintf(tmp_sql,"SELECT count(*) FROM `%s` WHERE `guild_id`='%d'",guild_member_db, g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); + return -1; } - + sql_res = mysql_store_result(&mysql_handle) ; + if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { + sql_row = mysql_fetch_row(sql_res); + + guild_member = atoi (sql_row[0]); + // printf("- Check members in guild %d : %d \n",g->guild_id,guild_member); + + } + mysql_free_result(sql_res) ; //resource free + // Delete old guild from sql if (flag&1||guild_member==0){ - StringBuf_Printf(&sbuf, "DELETE FROM `%s` WHERE `guild_id`='%d';\n",guild_db, g->guild_id); + // printf("- Delete guild %d from guild\n",g->guild_id); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d'",guild_db, g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (delete `guild`)- %s\n", mysql_error(&mysql_handle) ); + } } if (flag&2||guild_member==0){ // printf("- Delete guild %d from guild_member\n",g->guild_id); - StringBuf_Printf(&sbuf, "DELETE FROM `%s` WHERE `guild_id`='%d';\n",guild_member_db, g->guild_id); - StringBuf_Printf(&sbuf, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d';\n",char_db, g->guild_id); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d'",guild_member_db, g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (delete `guild_member`)- %s\n", mysql_error(&mysql_handle) ); + } + sprintf(tmp_sql, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d'",char_db, g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle) ); + } } if (flag&32||guild_member==0){ // printf("- Delete guild %d from guild_skill\n",g->guild_id); - StringBuf_Printf(&sbuf, "DELETE FROM `%s` WHERE `guild_id`='%d';\n",guild_skill_db, g->guild_id); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d'",guild_skill_db, g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (delete `guild_skill`)- %s\n", mysql_error(&mysql_handle) ); + } } if (flag&4||guild_member==0){ // printf("- Delete guild %d from guild_position\n",g->guild_id); - StringBuf_Printf(&sbuf, "DELETE FROM `%s` WHERE `guild_id`='%d';\n",guild_position_db, g->guild_id); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d'",guild_position_db, g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (delete `guild_position`)- %s\n", mysql_error(&mysql_handle) ); + } } if (flag&16||guild_member==0){ // printf("- Delete guild %d from guild_expulsion\n",g->guild_id); - StringBuf_Printf(&sbuf, "DELETE FROM `%s` WHERE `guild_id`='%d';\n",guild_expulsion_db, g->guild_id); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d'",guild_expulsion_db, g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (delete `guild_expulsion`)- %s\n", mysql_error(&mysql_handle) ); + } } if (flag&8||guild_member==0){ // printf("- Delete guild %d from guild_alliance\n",g->guild_id); - StringBuf_Printf(&sbuf, "DELETE FROM `%s` WHERE `guild_id`='%d' OR `alliance_id`='%d';\n",guild_alliance_db, g->guild_id,g->guild_id); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d' OR `alliance_id`='%d'",guild_alliance_db, g->guild_id,g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (delete `guild_alliance`)- %s\n", mysql_error(&mysql_handle) ); + } } if (flag&2||guild_member==0){ // printf("- Delete guild %d from char\n",g->guild_id); - StringBuf_Printf(&sbuf, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d';\n",char_db, g->guild_id); + sprintf(tmp_sql, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d'",char_db, g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (delete `guild_alliance`)- %s\n", mysql_error(&mysql_handle) ); + } } if (guild_member==0){ // printf("- Delete guild %d from guild_castle\n",g->guild_id); - StringBuf_Printf(&sbuf, "DELETE FROM `%s` WHERE `guild_id`='%d';\n",guild_castle_db, g->guild_id); + sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d'",guild_castle_db, g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (delete `guild_castle`)- %s\n", mysql_error(&mysql_handle) ); + } + db_foreach(castle_db_, _erase_guild, g->guild_id); } -#if 0 } -#endif guild_online_member = 0; i=0; @@ -115,13 +171,11 @@ int inter_guild_tosql(struct guild *g,int flag) if (g->member[i].account_id>0) guild_online_member++; i++; } - + // No member in guild , no need to create it in sql if (guild_member <= 0 && guild_online_member <=0) { inter_guild_storage_delete(g->guild_id); printf("No member in guild %d , break it! \n",g->guild_id); - if(mysql_query(&mysql_handle, StringBuf_Value(&sbuf)) ) - printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); return -2; } @@ -132,134 +186,131 @@ int inter_guild_tosql(struct guild *g,int flag) for(i=0;i<g->emblem_len;i++){ len+=sprintf(emblem_data+len,"%02x",(unsigned char)(g->emblem_data[i])); //printf("%02x",(unsigned char)(g->emblem_data[i])); - } + } emblem_data[len] = '\0'; //printf("- emblem_len = %d \n",g->emblem_len); - StringBuf_Printf(&sbuf, "INSERT INTO `%s` " + sprintf(tmp_sql,"INSERT INTO `%s` " "(`guild_id`, `name`,`master`,`guild_lv`,`connect_member`,`max_member`,`average_lv`,`exp`,`next_exp`,`skill_point`,`castle_id`,`mes1`,`mes2`,`emblem_len`,`emblem_id`,`emblem_data`) " - "VALUES ('%d', '%s', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%s', '%d', '%d', '%s');", + "VALUES ('%d', '%s', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%s', '%d', '%d', '%s')", guild_db, g->guild_id,t_name,jstrescapecpy(t_master,g->master), g->guild_lv,g->connect_member,g->max_member,g->average_lv,g->exp,g->next_exp,g->skill_point,g->castle_id, jstrescapecpy(t_mes1,g->mes1),jstrescapecpy(t_mes2,g->mes2),g->emblem_len,g->emblem_id,emblem_data); //printf(" %s\n",tmp_sql); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (insert `guild`)- %s\n", mysql_error(&mysql_handle) ); + } } if (flag&2||guild_member==0){ - struct StringBuf sbuf2; - StringBuf_Init(&sbuf2); - - first = 1; - - StringBuf_Printf(&sbuf,"REPLACE `%s` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`rsv1`,`rsv2`,`name`) VALUES \n", guild_member_db); - - StringBuf_Printf(&sbuf2, "UPDATE `%s` SET `guild_id`='%d' WHERE `char_id` IN (",char_db, g->guild_id); - - //printf("- Insert guild %d to guild_member\n",g->guild_id); - for(i=0;i<g->max_member;i++){ - if (g->member[i].account_id>0){ - struct guild_member *m = &g->member[i]; - if (first == 0) { - StringBuf_Printf(&sbuf , ", "); - StringBuf_Printf(&sbuf2, ", "); - } else - first = 0; - StringBuf_Printf(&sbuf, "('%d','%d','%d','%d','%d', '%d','%d','%d','%d','%d','%d','%d','%d','%d','%s')\n", - g->guild_id, - m->account_id,m->char_id, - m->hair,m->hair_color,m->gender, - m->class,m->lv,m->exp,m->exp_payper,m->online,m->position, - 0,0, - jstrescapecpy(t_member,m->name)); - - StringBuf_Printf(&sbuf2, "'%d'", m->char_id); - } - } - StringBuf_Printf(&sbuf, ";\n"); - StringBuf_Printf(&sbuf2,");\n"); - StringBuf_Append(&sbuf, &sbuf2); - StringBuf_Destroy(&sbuf2); + struct StringBuf sbuf; + struct StringBuf sbuf2; + int first = 1; + StringBuf_Init(&sbuf2); + StringBuf_Init(&sbuf); + + StringBuf_Printf(&sbuf,"REPLACE `%s` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`rsv1`,`rsv2`,`name`) VALUES \n", guild_member_db); + + StringBuf_Printf(&sbuf2, "UPDATE `%s` SET `guild_id`='%d' WHERE `char_id` IN (",char_db, g->guild_id); + + //printf("- Insert guild %d to guild_member\n",g->guild_id); + for(i=0;i<g->max_member;i++){ + if (g->member[i].account_id>0){ + struct guild_member *m = &g->member[i]; + if (first == 0) { + StringBuf_Printf(&sbuf , ", "); + StringBuf_Printf(&sbuf2, ", "); + } else + first = 0; + StringBuf_Printf(&sbuf, "('%d','%d','%d','%d','%d', '%d','%d','%d','%d','%d','%d','%d','%d','%d','%s')\n", + g->guild_id, + m->account_id,m->char_id, + m->hair,m->hair_color,m->gender, + m->class_,m->lv,m->exp,m->exp_payper,m->online,m->position, + 0,0, + jstrescapecpy(t_member,m->name)); + + StringBuf_Printf(&sbuf2, "'%d'", m->char_id); + } + } + StringBuf_Printf(&sbuf2,")"); + + if(mysql_query(&mysql_handle, StringBuf_Value(&sbuf))) + printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); + + if(mysql_query(&mysql_handle, StringBuf_Value(&sbuf2))) + printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); + + StringBuf_Destroy(&sbuf2); + StringBuf_Destroy(&sbuf); } - + if (flag&4||guild_member==0){ - first = 1; //printf("- Insert guild %d to guild_position\n",g->guild_id); - StringBuf_Printf(&sbuf ,"INSERT INTO `%s` (`guild_id`,`position`,`name`,`mode`,`exp_mode`) VALUES ", guild_position_db); for(i=0;i<MAX_GUILDPOSITION;i++){ - if (first == 0) - StringBuf_Printf(&sbuf , ", "); - else - first = 0; struct guild_position *p = &g->position[i]; - StringBuf_Printf(&sbuf , "('%d','%d', '%s','%d','%d')", - g->guild_id, i, jstrescapecpy(t_position,p->name),p->mode,p->exp_mode); + sprintf(tmp_sql,"INSERT INTO `%s` (`guild_id`,`position`,`name`,`mode`,`exp_mode`) VALUES ('%d','%d', '%s','%d','%d')", + guild_position_db, g->guild_id, i, jstrescapecpy(t_position,p->name),p->mode,p->exp_mode); + //printf(" %s\n",tmp_sql); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (insert `guild_position`)- %s\n", mysql_error(&mysql_handle) ); + } } - StringBuf_Printf(&sbuf ,";\n"); } if (flag&8||guild_member==0){ - first = 1; - StringBuf_Printf(&sbuf , "INSERT INTO `%s` (`guild_id`,`opposition`,`alliance_id`,`name`) VALUES ", guild_alliance_db); //printf("- Insert guild %d to guild_alliance\n",g->guild_id); for(i=0;i<MAX_GUILDALLIANCE;i++){ struct guild_alliance *a=&g->alliance[i]; if(a->guild_id>0){ - if (first == 0) - StringBuf_Printf(&sbuf , ", "); - else - first = 0; - StringBuf_Printf(&sbuf , "('%d','%d','%d','%s')", - g->guild_id,a->opposition,a->guild_id,jstrescapecpy(t_alliance,a->name)); - - StringBuf_Printf(&sbuf , ", ('%d','%d','%d','%s')", - a->guild_id,a->opposition,g->guild_id,t_name); + sprintf(tmp_sql,"INSERT INTO `%s` (`guild_id`,`opposition`,`alliance_id`,`name`) " + "VALUES ('%d','%d','%d','%s')", + guild_alliance_db, g->guild_id,a->opposition,a->guild_id,jstrescapecpy(t_alliance,a->name)); //printf(" %s\n",tmp_sql); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (insert `guild_alliance`)- %s\n", mysql_error(&mysql_handle) ); + } + sprintf(tmp_sql,"INSERT INTO `%s` (`guild_id`,`opposition`,`alliance_id`,`name`) " + "VALUES ('%d','%d','%d','%s')", + guild_alliance_db, a->guild_id,a->opposition,g->guild_id,t_name); + //printf(" %s\n",tmp_sql); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (insert `guild_alliance`)- %s\n", mysql_error(&mysql_handle) ); + } } } - StringBuf_Printf(&sbuf ,";\n"); } if (flag&16||guild_member==0){ - first = 1; //printf("- Insert guild %d to guild_expulsion\n",g->guild_id); - StringBuf_Printf(&sbuf, "INSERT INTO `%s` (`guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3`) VALUES ", - guild_expulsion_db); for(i=0;i<MAX_GUILDEXPLUSION;i++){ struct guild_explusion *e=&g->explusion[i]; if(e->account_id>0){ - if (first == 0) - StringBuf_Printf(&sbuf , ", "); - else - first = 0; - StringBuf_Printf(&sbuf, "('%d','%s','%s','%s','%d','%d','%d','%d')", - g->guild_id, jstrescapecpy(t_ename,e->name),jstrescapecpy(t_emes,e->mes),e->acc,e->account_id,e->rsv1,e->rsv2,e->rsv3 ); + sprintf(tmp_sql,"INSERT INTO `%s` (`guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3`) " + "VALUES ('%d','%s','%s','%s','%d','%d','%d','%d')", + guild_expulsion_db, g->guild_id, + jstrescapecpy(t_ename,e->name),jstrescapecpy(t_emes,e->mes),e->acc,e->account_id,e->rsv1,e->rsv2,e->rsv3 ); //printf(" %s\n",tmp_sql); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (insert `guild_expulsion`)- %s\n", mysql_error(&mysql_handle) ); + } } } - StringBuf_Printf(&sbuf ,";\n"); } if (flag&32||guild_member==0){ - first = 1; //printf("- Insert guild %d to guild_skill\n",g->guild_id); - StringBuf_Printf(&sbuf,"INSERT INTO `%s` (`guild_id`,`id`,`lv`) VALUES ", guild_skill_db); for(i=0;i<MAX_GUILDSKILL;i++){ if (g->skill[i].id>0){ - if (first == 0) - StringBuf_Printf(&sbuf , ", "); - else - first = 0; - StringBuf_Printf(&sbuf, "('%d','%d','%d')", - g->guild_id,g->skill[i].id,g->skill[i].lv); + sprintf(tmp_sql,"INSERT INTO `%s` (`guild_id`,`id`,`lv`) VALUES ('%d','%d','%d')", + guild_skill_db, g->guild_id,g->skill[i].id,g->skill[i].lv); + //printf("%s\n",tmp_sql); + if(mysql_query(&mysql_handle, tmp_sql) ) { + printf("DB server Error (insert `guild_skill`)- %s\n", mysql_error(&mysql_handle) ); + } } } - StringBuf_Printf(&sbuf ,";\n"); } - if(mysql_query(&mysql_handle, StringBuf_Value(&sbuf))) - printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); - - StringBuf_Destroy(&sbuf); - printf("Save guild done\n"); return 0; } @@ -272,15 +323,15 @@ struct guild * inter_guild_fromsql(int guild_id) char *pstr; struct guild *g; - if (guild_id==0) return 0; + if (guild_id<=0) return 0; - g = numdb_search(guild_db_,guild_id); + g = (struct guild*)numdb_search(guild_db_,guild_id); if (g != NULL) return g; - - g = (struct guild *) malloc(sizeof(struct guild)); + + g = (struct guild*)aMalloc(sizeof(struct guild)); memset(g,0,sizeof(struct guild)); - + // printf("Retrieve guild information from sql ......\n"); // printf("- Read guild %d from sql \n",guild_id); @@ -289,25 +340,28 @@ struct guild * inter_guild_fromsql(int guild_id) //printf(" %s\n",tmp_sql); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (select `guild`)- %s\n", mysql_error(&mysql_handle) ); - free(g); + aFree(g); return 0; } - + sql_res = mysql_store_result(&mysql_handle) ; if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { sql_row = mysql_fetch_row(sql_res); if (sql_row==NULL) { mysql_free_result(sql_res); - free(g); + aFree(g); return 0; } - + g->guild_id=atoi(sql_row[0]); strncpy(g->name,sql_row[1],24); strncpy(g->master,sql_row[2],24); g->guild_lv=atoi(sql_row[3]); g->connect_member=atoi(sql_row[4]); - g->max_member=atoi(sql_row[5]); + if (atoi(sql_row[5]) > MAX_GUILD) // Fix reduction of MAX_GUILD [PoW] + g->max_member = MAX_GUILD; + else + g->max_member = atoi(sql_row[5]); g->average_lv=atoi(sql_row[6]); g->exp=atoi(sql_row[7]); g->next_exp=atoi(sql_row[8]); @@ -327,7 +381,7 @@ struct guild * inter_guild_fromsql(int guild_id) if(c2>='a' && c2<='f')x2=c2-'a'+10; if(c2>='A' && c2<='F')x2=c2-'A'+10; g->emblem_data[i]=(x1<<4)|x2; - } + } } mysql_free_result(sql_res); @@ -337,7 +391,7 @@ struct guild * inter_guild_fromsql(int guild_id) //printf(" %s\n",tmp_sql); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (select `guild_member`)- %s\n", mysql_error(&mysql_handle) ); - free(g); + aFree(g); return 0; } sql_res = mysql_store_result(&mysql_handle) ; @@ -350,43 +404,47 @@ struct guild * inter_guild_fromsql(int guild_id) m->hair=atoi(sql_row[3]); m->hair_color=atoi(sql_row[4]); m->gender=atoi(sql_row[5]); - m->class=atoi(sql_row[6]); + m->class_=atoi(sql_row[6]); m->lv=atoi(sql_row[7]); m->exp=atoi(sql_row[8]); m->exp_payper=atoi(sql_row[9]); - m->online=atoi(sql_row[10]); - m->position=atoi(sql_row[11]); + m->online=atoi(sql_row[10]); + if (atoi(sql_row[11]) >= MAX_GUILDPOSITION) // Fix reduction of MAX_GUILDPOSITION [PoW] + m->position = MAX_GUILDPOSITION - 1; + else + m->position = atoi(sql_row[11]); + strncpy(m->name,sql_row[14],24); } } mysql_free_result(sql_res); - + //printf("- Read guild_position %d from sql \n",guild_id); sprintf(tmp_sql,"SELECT `guild_id`,`position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'",guild_position_db, guild_id); //printf(" %s\n",tmp_sql); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (select `guild_position`)- %s\n", mysql_error(&mysql_handle) ); - free(g); + aFree(g); return 0; } sql_res = mysql_store_result(&mysql_handle) ; if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { int i; for(i=0;((sql_row = mysql_fetch_row(sql_res))&&i<MAX_GUILDPOSITION);i++){ - int position = atoi(sql_row[1]); + int position = atoi(sql_row[1]); struct guild_position *p = &g->position[position]; - strncpy(p->name,sql_row[2],24); + strncpy(p->name,sql_row[2],24); p->mode=atoi(sql_row[3]); - p->exp_mode=atoi(sql_row[4]); + p->exp_mode=atoi(sql_row[4]); } } - mysql_free_result(sql_res); + mysql_free_result(sql_res); //printf("- Read guild_alliance %d from sql \n",guild_id); sprintf(tmp_sql,"SELECT `guild_id`,`opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'",guild_alliance_db, guild_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (select `guild_alliance`)- %s\n", mysql_error(&mysql_handle) ); - free(g); + aFree(g); return 0; } sql_res = mysql_store_result(&mysql_handle) ; @@ -400,12 +458,12 @@ struct guild * inter_guild_fromsql(int guild_id) } } mysql_free_result(sql_res); - + //printf("- Read guild_expulsion %d from sql \n",guild_id); sprintf(tmp_sql,"SELECT `guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3` FROM `%s` WHERE `guild_id`='%d'",guild_expulsion_db, guild_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (select `guild_expulsion`)- %s\n", mysql_error(&mysql_handle) ); - free(g); + aFree(g); return 0; } sql_res = mysql_store_result(&mysql_handle) ; @@ -421,16 +479,16 @@ struct guild * inter_guild_fromsql(int guild_id) e->rsv1=atoi(sql_row[5]); e->rsv2=atoi(sql_row[6]); e->rsv3=atoi(sql_row[7]); - + } } mysql_free_result(sql_res); - + //printf("- Read guild_skill %d from sql \n",guild_id); sprintf(tmp_sql,"SELECT `guild_id`,`id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`",guild_skill_db, guild_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (select `guild_skill`)- %s\n", mysql_error(&mysql_handle) ); - free(g); + aFree(g); return 0; } sql_res = mysql_store_result(&mysql_handle) ; @@ -442,7 +500,7 @@ struct guild * inter_guild_fromsql(int guild_id) } } mysql_free_result(sql_res); - + // printf("Successfully retrieve guild information from sql!\n"); numdb_insert(guild_db_, guild_id,g); @@ -450,21 +508,40 @@ struct guild * inter_guild_fromsql(int guild_id) return g; } -// Save guild_castle to sql +#if 1 +static int _set_guild_castle(void *key, void *data, va_list ap) { + int castle_id = va_arg(ap, int); + int guild_id = va_arg(ap, int); + struct guild * g = (struct guild *) data; + + if (g->castle_id == castle_id) + g->castle_id = -1; + if (g->guild_id == guild_id) + g->castle_id = castle_id; + return 0; +} +#endif + int inter_guildcastle_tosql(struct guild_castle *gc) { - // `guild_castle` (`castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`, `visibleC`, `visibleG0`, `visibleG1`, `visibleG2`, `visibleG3`, `visibleG4`, `visibleG5`, `visibleG6`, `visibleG7`) - - if (gc==NULL) return 0; - //printf("Save to guild_castle\n"); - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `castle_id`='%d'",guild_castle_db, gc->castle_id); - //printf(" %s\n",tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql) ) { - printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); + struct guild_castle *gcopy; + if(gc == NULL || gc->castle_id < 0 ){ //gc->castle_id can be == 0 (for the 1st castle it's == 0) [Lupus] return 0; } - - sprintf(tmp_sql,"INSERT INTO `%s` " + //printf("[Guild Castle %02i]: Save...\n",gc->castle_id); + gcopy = (struct guild_castle *) numdb_search(castle_db_,gc->castle_id); + if (gcopy == NULL) { + gcopy = (struct guild_castle *) aMalloc(sizeof(struct guild_castle)); + numdb_insert(castle_db_, gc->castle_id, gcopy); + } else { + //if the castle data hasn't been changed, then we don't write it into SQL + if ((gc->guild_id == gcopy->guild_id ) && ( gc->economy == gcopy->economy ) && ( gc->defense == gcopy->defense ) && ( gc->triggerE == gcopy->triggerE ) && ( gc->triggerD == gcopy->triggerD ) && ( gc->nextTime == gcopy->nextTime ) && ( gc->payTime == gcopy->payTime ) && ( gc->createTime == gcopy->createTime ) && ( gc->visibleC == gcopy->visibleC ) && ( gc->visibleG0 == gcopy->visibleG0 ) && ( gc->visibleG1 == gcopy->visibleG1 ) && ( gc->visibleG2 == gcopy->visibleG2 ) && ( gc->visibleG3 == gcopy->visibleG3 ) && ( gc->visibleG4 == gcopy->visibleG4 ) && ( gc->visibleG5 == gcopy->visibleG5 ) && ( gc->visibleG6 == gcopy->visibleG6 ) && ( gc->visibleG7 == gcopy->visibleG7 ) && ( gc->Ghp0 == gcopy->Ghp0 ) && ( gc->Ghp1 == gcopy->Ghp1 ) && ( gc->Ghp2 == gcopy->Ghp2 ) && ( gc->Ghp3 == gcopy->Ghp3 ) && ( gc->Ghp4 == gcopy->Ghp4 ) && ( gc->Ghp5 == gcopy->Ghp5 ) && ( gc->Ghp6 == gcopy->Ghp6 ) && ( gc->Ghp7 == gcopy->Ghp7 )) + return 0; + } + //printf("[Guild Castle %02i]: Save... ->SQL\n",gc->castle_id); + memcpy(gcopy, gc, sizeof(struct guild_castle)); + + sprintf(tmp_sql,"REPLACE INTO `%s` " "(`castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`," "`visibleC`, `visibleG0`, `visibleG1`, `visibleG2`, `visibleG3`, `visibleG4`, `visibleG5`, `visibleG6`, `visibleG7`," "`Ghp0`, `Ghp1`, `Ghp2`, `Ghp3`, `Ghp4`, `Ghp5`, `Ghp6`, `Ghp7`)" @@ -472,35 +549,35 @@ int inter_guildcastle_tosql(struct guild_castle *gc) guild_castle_db, gc->castle_id, gc->guild_id, gc->economy, gc->defense, gc->triggerE, gc->triggerD, gc->nextTime, gc->payTime, gc->createTime, gc->visibleC, gc->visibleG0, gc->visibleG1, gc->visibleG2, gc->visibleG3, gc->visibleG4, gc->visibleG5, gc->visibleG6, gc->visibleG7, gc->Ghp0, gc->Ghp1, gc->Ghp2, gc->Ghp3, gc->Ghp4, gc->Ghp5, gc->Ghp6, gc->Ghp7); - //printf(" %s\n",tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql) ) { - printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); - return 0; - } - sprintf(tmp_sql,"UPDATE `%s` SET `castle_id`='-1' WHERE `castle_id`='%d'",guild_db, gc->castle_id); - //printf(" %s\n",tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql) ) { - printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); - return 0; - } - - sprintf(tmp_sql,"UPDATE `%s` SET `castle_id`='%d' WHERE `guild_id`='%d'",guild_db, gc->castle_id,gc->guild_id); //printf(" %s\n",tmp_sql); + if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); return 0; } + + db_foreach(guild_db_, _set_guild_castle, gc->castle_id,gc->guild_id); return 0; } + // Read guild_castle from sql int inter_guildcastle_fromsql(int castle_id,struct guild_castle *gc) { - + struct guild_castle *gcopy; if (gc==NULL) return 0; //printf("Read from guild_castle\n"); - memset(gc,0,sizeof(struct guild_castle)); + + gcopy = (struct guild_castle*)numdb_search(castle_db_, castle_id); + if (gcopy == NULL) { + gcopy = (struct guild_castle*)aMalloc(sizeof(struct guild_castle)); + numdb_insert(castle_db_, gc->castle_id, gcopy); + } else { + memcpy(gc, gcopy, sizeof(struct guild_castle)); + return 0; + } + gc->castle_id=castle_id; if (castle_id==-1) return 0; sprintf(tmp_sql,"SELECT `castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`, " @@ -518,7 +595,7 @@ int inter_guildcastle_fromsql(int castle_id,struct guild_castle *gc) mysql_free_result(sql_res); return 0; } - + gc->guild_id = atoi (sql_row[1]); gc->economy = atoi (sql_row[2]); gc->defense = atoi (sql_row[3]); @@ -544,11 +621,14 @@ int inter_guildcastle_fromsql(int castle_id,struct guild_castle *gc) gc->Ghp5 = atoi (sql_row[23]); gc->Ghp6 = atoi (sql_row[24]); gc->Ghp7 = atoi (sql_row[25]); - + //printf("Read Castle %d of guild %d from sql \n",castle_id,gc->guild_id); } mysql_free_result(sql_res) ; //resource free + + memcpy(gcopy, gc, sizeof(struct guild_castle)); + return 0; } @@ -559,7 +639,7 @@ int inter_guild_readdb() FILE *fp; char line[1024]; for (i=0;i<100;i++) guild_exp[i]=0; - + fp=fopen("db/exp_guild.txt","r"); if(fp==NULL){ printf("can't read db/exp_guild.txt\n"); @@ -585,17 +665,14 @@ int inter_guild_sql_init() guild_db_=numdb_init(); castle_db_=numdb_init(); - guild_expcache_db_=numdb_init(); - guild_infoevent_db_=numdb_init(); - guild_castleinfoevent_db_=numdb_init(); - + printf("interserver guild memory initialize.... (%d byte)\n",sizeof(struct guild)); - guild_pt = calloc(sizeof(struct guild), 1); - guild_pt2= calloc(sizeof(struct guild), 1); - guildcastle_pt=calloc(sizeof(struct guild_castle), 1); - + guild_pt = (struct guild*)aCalloc(sizeof(struct guild), 1); + guild_pt2= (struct guild*)aCalloc(sizeof(struct guild), 1); + guildcastle_pt = (struct guild_castle*)aCalloc(sizeof(struct guild_castle), 1); + inter_guild_readdb(); // Read exp - + sprintf (tmp_sql , "SELECT count(*) FROM `%s`",guild_db); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); @@ -614,18 +691,41 @@ int inter_guild_sql_init() printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); exit(0); } - + sql_res = mysql_store_result(&mysql_handle) ; sql_row = mysql_fetch_row(sql_res); guild_newid = atoi(sql_row[0])+1; mysql_free_result(sql_res); } - + printf("set guild_newid: %d.......\n",guild_newid); return 0; } +int guild_db_final (void *k, void *data, va_list ap) +{ + struct guild *g = (struct guild *) data; + if (g) aFree(g); + return 0; +} +int castle_db_final (void *k, void *data, va_list ap) +{ + struct guild_castle *gc = (struct guild_castle *) data; + if (gc) aFree(gc); + return 0; +} +void inter_guild_sql_final() +{ + if (guild_pt) aFree(guild_pt); + if (guild_pt2) aFree(guild_pt2); + if (guildcastle_pt) aFree(guildcastle_pt); + + numdb_final(guild_db_, guild_db_final); + numdb_final(castle_db_, castle_db_final); + + return; +} // Get guild by its name struct guild* search_guildname(char *str) @@ -655,7 +755,7 @@ int guild_check_empty(struct guild *g) return 0; } } - + // ’N‚à‚¢‚È‚¢‚̂ʼnðŽU mapif_guild_broken(g->guild_id,0); inter_guild_storage_delete(g->guild_id); @@ -707,7 +807,7 @@ int guild_calcinfo(struct guild *g) nextexp = guild_nextexp(g->guild_lv); } } - + // ƒMƒ‹ƒh‚ÌŽŸ‚ÌŒoŒ±’l g->next_exp = guild_nextexp(g->guild_lv); @@ -721,13 +821,13 @@ int guild_calcinfo(struct guild *g) if(g->member[i].account_id>0){ g->average_lv+=g->member[i].lv; c++; - + if(g->member[i].online>0) g->connect_member++; } } if(c) g->average_lv/=c; - + // ‘Sƒf[ƒ^‚ð‘—‚é•K—v‚ª‚ ‚è‚»‚¤ if( g->max_member!=before.max_member || g->guild_lv!=before.guild_lv || @@ -735,7 +835,7 @@ int guild_calcinfo(struct guild *g) mapif_guild_info(-1,g); return 1; } - + return 0; } @@ -818,9 +918,9 @@ int mapif_guild_memberinfoshort(struct guild *g,int idx) WBUFL(buf, 2)=g->guild_id; WBUFL(buf, 6)=g->member[idx].account_id; WBUFL(buf,10)=g->member[idx].char_id; - WBUFB(buf,14)=g->member[idx].online; + WBUFB(buf,14)=(unsigned char)g->member[idx].online; WBUFW(buf,15)=g->member[idx].lv; - WBUFW(buf,17)=g->member[idx].class; + WBUFW(buf,17)=g->member[idx].class_; mapif_sendall(buf,19); return 0; } @@ -838,7 +938,7 @@ int mapif_guild_broken(int guild_id,int flag) } // ƒMƒ‹ƒh“à”Œ¾ -int mapif_guild_message(int guild_id,int account_id,char *mes,int len) +int mapif_guild_message(int guild_id,int account_id,char *mes,int len, int sfd) { unsigned char buf[512]; WBUFW(buf,0)=0x3837; @@ -846,7 +946,7 @@ int mapif_guild_message(int guild_id,int account_id,char *mes,int len) WBUFL(buf,4)=guild_id; WBUFL(buf,8)=account_id; memcpy(WBUFP(buf,12),mes,len); - mapif_sendall(buf,len+12); + mapif_sendallwos(sfd, buf,len+12); return 0; } @@ -966,6 +1066,7 @@ int mapif_guild_castle_datasave(int castle_id,int index,int value) // <Agit int mapif_guild_castle_alldataload(int fd) { struct guild_castle* gc = guildcastle_pt; + struct guild_castle *gcopy; int i, len = 4; WFIFOW(fd,0) = 0x3842; @@ -1004,6 +1105,14 @@ int mapif_guild_castle_alldataload(int fd) { gc->Ghp6 = atoi(sql_row[24]); gc->Ghp7 = atoi(sql_row[25]); memcpy(WFIFOP(fd,len), gc, sizeof(struct guild_castle)); + + gcopy = (struct guild_castle*)numdb_search(castle_db_,gc->castle_id); + if (gcopy == NULL) { + gcopy = (struct guild_castle *) aMalloc(sizeof(struct guild_castle)); + numdb_insert(castle_db_, gc->castle_id, gcopy); + } + memcpy(gcopy, gc, sizeof(struct guild_castle)); + len += sizeof(struct guild_castle); } } @@ -1024,7 +1133,7 @@ int mapif_parse_CreateGuild(int fd,int account_id,char *name,struct guild_member { struct guild *g; int i; - + printf("CreateGuild\n"); g=search_guildname(name); if(g!=NULL&&g->guild_id>0){ @@ -1038,38 +1147,38 @@ int mapif_parse_CreateGuild(int fd,int account_id,char *name,struct guild_member memcpy(g->name,name,24); memcpy(g->master,master->name,24); memcpy(&g->member[0],master,sizeof(struct guild_member)); - + g->position[0].mode=0x11; - strcpy(g->position[ 0].name,"GuildMaster"); + strcpy(g->position[0].name,"GuildMaster"); strcpy(g->position[MAX_GUILDPOSITION-1].name,"Newbie"); for(i=1;i<MAX_GUILDPOSITION-1;i++) sprintf(g->position[i].name,"Position %d",i+1); - + // Initialize guild property g->max_member=16; g->average_lv=master->lv; g->castle_id=-1; for(i=0;i<MAX_GUILDSKILL;i++) g->skill[i].id=i + GD_SKILLBASE; - + // Save to sql printf("Create initialize OK!\n"); i=inter_guild_tosql(g,255); - + if (i<0) { mapif_guild_created(fd,account_id,NULL); return 0; } - + // Report to client mapif_guild_created(fd,account_id,g); mapif_guild_info(fd,g); - + if(log_inter) inter_log("guild %s (id=%d) created by master %s (id=%d)" RETCODE, name, g->guild_id, master->name, master->account_id ); - - + + return 0; } // Return guild info to client @@ -1089,15 +1198,15 @@ int mapif_parse_GuildAddMember(int fd,int guild_id,struct guild_member *m) { struct guild *g = inter_guild_fromsql(guild_id); int i; - + if(g==NULL||g->guild_id<=0){ mapif_guild_memberadded(fd,guild_id,m->account_id,m->char_id,1); return 0; } - + for(i=0;i<g->max_member;i++){ if(g->member[i].account_id==0){ - + memcpy(&g->member[i],m,sizeof(struct guild_member)); mapif_guild_memberadded(fd,guild_id,m->account_id,m->char_id,0); guild_calcinfo(g); @@ -1114,7 +1223,7 @@ int mapif_parse_GuildAddMember(int fd,int guild_id,struct guild_member *m) int mapif_parse_GuildLeave(int fd,int guild_id,int account_id,int char_id,int flag,const char *mes) { struct guild *g= inter_guild_fromsql(guild_id); - + if(g!=NULL&&g->guild_id>0){ int i; for(i=0;i<g->max_member;i++){ @@ -1122,7 +1231,7 @@ int mapif_parse_GuildLeave(int fd,int guild_id,int account_id,int char_id,int fl g->member[i].char_id==char_id){ printf("%d %d\n",i, (int)(&g->member[i])); printf("%d %s\n",i, g->member[i].name); - + if(flag){ // ’Ç•ú‚ÌꇒǕúƒŠƒXƒg‚É“ü‚ê‚é int j; for(j=0;j<MAX_GUILDEXPLUSION;j++){ @@ -1139,17 +1248,17 @@ int mapif_parse_GuildLeave(int fd,int guild_id,int account_id,int char_id,int fl memcpy(g->explusion[j].name,g->member[i].name,24); memcpy(g->explusion[j].mes,mes,40); } - + mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes); printf("%d %d\n",i, (int)(&g->member[i])); printf("%d %s\n",i, (&g->member[i])->name); memset(&g->member[i],0,sizeof(struct guild_member)); - + if( guild_check_empty(g)==0 ) mapif_guild_info(-1,g);// ‚Ü‚¾l‚ª‚¢‚é‚̂Ńf[ƒ^‘—M /* else - inter_guild_save(); // ‰ðŽU‚µ‚½‚̂ňꉞƒZ[ƒu + inter_guild_save(); // ‰ðŽU‚µ‚½‚̂ňê‰cZ[ƒu return 0;*/ } } @@ -1162,31 +1271,33 @@ int mapif_parse_GuildLeave(int fd,int guild_id,int account_id,int char_id,int fl } /* mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes); */ } - + return 0; } - // Change member info int mapif_parse_GuildChangeMemberInfoShort(int fd,int guild_id, - int account_id,int char_id,int online,int lv,int class) + int account_id,int char_id,int online,int lv,int class_) { // Could speed up by manipulating only guild_member struct guild * g= inter_guild_fromsql(guild_id); - int i,alv,c; + int i,alv,c, idx; if(g==NULL||g->guild_id<=0) return 0; - + g->connect_member=0; - + + idx = -1; + for(i=0,alv=0,c=0;i<g->max_member;i++){ if( g->member[i].account_id==account_id && g->member[i].char_id==char_id){ - + g->member[i].online=online; g->member[i].lv=lv; - g->member[i].class=class; + g->member[i].class_=class_; mapif_guild_memberinfoshort(g,i); + idx = i; } if( g->member[i].account_id>0 ){ alv+=g->member[i].lv; @@ -1195,11 +1306,19 @@ int mapif_parse_GuildChangeMemberInfoShort(int fd,int guild_id, if( g->member[i].online ) g->connect_member++; } - // •½‹ÏƒŒƒxƒ‹ - g->average_lv=alv/c; - - inter_guild_tosql(g,3); // Change guild & guild_member - + + if (c) + // •½‹ÏƒŒƒxƒ‹ + g->average_lv=alv/c; + + sprintf(tmp_sql, "UPDATE `%s` SET `connect_member`=%d,`average_lv`=%d WHERE `guild_id`='%d'", guild_db, g->connect_member, g->average_lv, g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) + printf("DB server Error: %s - %s\n", tmp_sql, mysql_error(&mysql_handle) ); + + sprintf(tmp_sql, "UPDATE `%s` SET `online`=%d,`lv`=%d,`class`=%d WHERE `char_id`=%d", guild_member_db, g->member[idx].online, g->member[idx].lv, g->member[idx].class_, g->member[idx].char_id); + if(mysql_query(&mysql_handle, tmp_sql) ) + printf("DB server Error: %s - %s\n", tmp_sql, mysql_error(&mysql_handle) ); + return 0; } @@ -1209,7 +1328,7 @@ int mapif_parse_BreakGuild(int fd,int guild_id) struct guild *g= inter_guild_fromsql(guild_id); if(g==NULL) return 0; - + // Delete guild from sql //printf("- Delete guild %d from guild\n",guild_id); sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d'",guild_db, guild_id); @@ -1241,32 +1360,34 @@ int mapif_parse_BreakGuild(int fd,int guild_id) if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (delete `guild_position`)- %s\n", mysql_error(&mysql_handle) ); } - + //printf("- Delete guild %d from guild_castle\n",guild_id); sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d'",guild_castle_db, guild_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (delete `guild_position`)- %s\n", mysql_error(&mysql_handle) ); } - + + db_foreach(castle_db_, _erase_guild, guild_id); + //printf("- Update guild %d of char\n",guild_id); sprintf(tmp_sql, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d'",char_db, guild_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (delete `guild_position`)- %s\n", mysql_error(&mysql_handle) ); } - + inter_guild_storage_delete(guild_id); mapif_guild_broken(guild_id,0); - + if(log_inter) inter_log("guild %s (id=%d) broken" RETCODE,g->name,guild_id); - + return 0; } // ƒMƒ‹ƒhƒƒbƒZ[ƒW‘—M int mapif_parse_GuildMessage(int fd,int guild_id,int account_id,char *mes,int len) { - return mapif_guild_message(guild_id,account_id,mes,len); + return mapif_guild_message(guild_id,account_id,mes,len, fd); } // ƒMƒ‹ƒhŠî–{ƒf[ƒ^•ÏX—v‹ int mapif_parse_GuildBasicInfoChange(int fd,int guild_id, @@ -1307,7 +1428,7 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int cha struct guild * g = inter_guild_fromsql(guild_id); //printf("GuildMemberInfoChange %s \n",(type==GMI_EXP)?"GMI_EXP":"OTHER"); - + if(g==NULL){ return 0; } @@ -1322,21 +1443,34 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int cha } switch(type){ case GMI_POSITION: // –ðE - g->member[i].position=*((int *)data); - break; - case GMI_EXP: { // EXP - int exp,oldexp=g->member[i].exp; - exp=g->member[i].exp=*((unsigned int *)data); - g->exp+=(exp-oldexp); - guild_calcinfo(g); // LvƒAƒbƒv”»’f - mapif_guild_basicinfochanged(guild_id,GBI_EXP,&g->exp,4); - }break; + { + g->member[i].position=*((int *)data); + mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len); + inter_guild_tosql(g,3); // Change guild & guild_member + break; + } + case GMI_EXP: + { // EXP + int exp,oldexp=g->member[i].exp; + exp=g->member[i].exp=*((unsigned int *)data); + g->exp+=(exp-oldexp); + guild_calcinfo(g); // LvƒAƒbƒv”»’f + mapif_guild_basicinfochanged(guild_id,GBI_EXP,&g->exp,4); + mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len); + + sprintf(tmp_sql, "UPDATE `%s` SET `guild_lv`=%d,`connect_member`=%d,`max_member`=%d,`average_lv`=%d,`exp`=%d,`next_exp`=%d,`skill_point`=%d WHERE `guild_id`='%d'", guild_db, g->guild_lv, g->connect_member, g->max_member, g->average_lv, g->exp, g->next_exp, g->skill_point, g->guild_id); + if(mysql_query(&mysql_handle, tmp_sql) ) + printf("DB server Error: %s - %s\n", tmp_sql, mysql_error(&mysql_handle) ); + + sprintf(tmp_sql, "UPDATE `%s` SET `exp`=%d WHERE `char_id`=%d", guild_member_db, g->member[i].exp, g->member[i].char_id); + if(mysql_query(&mysql_handle, tmp_sql) ) + printf("DB server Error: %s - %s\n", tmp_sql, mysql_error(&mysql_handle) ); + break; + } default: - printf("int_guild: GuildMemberInfoChange: Unknown type %d\n",type); - break; + printf("int_guild: GuildMemberInfoChange: Unknown type %d\n",type); + break; } - mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len); - inter_guild_tosql(g,3); // Change guild & guild_member return 0; } @@ -1362,10 +1496,11 @@ int mapif_parse_GuildSkillUp(int fd,int guild_id,int skill_num,int account_id) struct guild *g = inter_guild_fromsql(guild_id); int idx = skill_num - GD_SKILLBASE; + if(g == NULL || idx < 0 || idx >= MAX_GUILDSKILL) return 0; //printf("GuildSkillUp\n"); - + if( g->skill_point>0 && g->skill[idx].id>0 && g->skill[idx].lv<10 ){ g->skill[idx].lv++; @@ -1388,10 +1523,10 @@ int mapif_parse_GuildAlliance(int fd,int guild_id1,int guild_id2, int j,i; g[0]= inter_guild_fromsql(guild_id1); g[1]= inter_guild_fromsql(guild_id2); - + if(g[0]==NULL || g[1]==NULL || g[0]->guild_id ==0 || g[1]->guild_id==0) return 0; - + if(!(flag&0x8)){ for(i=0;i<2-(flag&1);i++){ for(j=0;j<MAX_GUILDALLIANCE;j++) @@ -1422,7 +1557,7 @@ int mapif_parse_GuildAlliance(int fd,int guild_id1,int guild_id2, int mapif_parse_GuildNotice(int fd,int guild_id,const char *mes1,const char *mes2) { struct guild *g= inter_guild_fromsql(guild_id); - + if(g==NULL||g->guild_id<=0) return 0; memcpy(g->mes1,mes1,60); @@ -1434,7 +1569,7 @@ int mapif_parse_GuildNotice(int fd,int guild_id,const char *mes1,const char *mes int mapif_parse_GuildEmblem(int fd,int len,int guild_id,int dummy,const char *data) { struct guild * g= inter_guild_fromsql(guild_id); - + if(g==NULL||g->guild_id<=0) return 0; memcpy(g->emblem_data,data,len); @@ -1497,7 +1632,7 @@ int mapif_parse_GuildCastleDataSave(int fd,int castle_id,int index,int value) struct guild *g=inter_guild_fromsql(gid); if(log_inter) inter_log("guild %s (id=%d) %s castle id=%d" RETCODE, - (g)?g->name:"??" ,gid, (value)?"occupy":"abandon", index); + (g)?g->name:"??" ,gid, (value)?"occupy":"abandon", castle_id); } gc->guild_id = value; break; @@ -1548,21 +1683,21 @@ int mapif_parse_GuildCheck(int fd,int guild_id,int account_id,int char_id) int inter_guild_parse_frommap(int fd) { switch(RFIFOW(fd,0)){ - case 0x3030: mapif_parse_CreateGuild(fd,RFIFOL(fd,4),RFIFOP(fd,8),(struct guild_member *)RFIFOP(fd,32)); break; + case 0x3030: mapif_parse_CreateGuild(fd,RFIFOL(fd,4),(char*)RFIFOP(fd,8),(struct guild_member *)RFIFOP(fd,32)); break; case 0x3031: mapif_parse_GuildInfo(fd,RFIFOL(fd,2)); break; case 0x3032: mapif_parse_GuildAddMember(fd,RFIFOL(fd,4),(struct guild_member *)RFIFOP(fd,8)); break; - case 0x3034: mapif_parse_GuildLeave(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOP(fd,15)); break; + case 0x3034: mapif_parse_GuildLeave(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),(const char*)RFIFOP(fd,15)); break; case 0x3035: mapif_parse_GuildChangeMemberInfoShort(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17)); break; case 0x3036: mapif_parse_BreakGuild(fd,RFIFOL(fd,2)); break; - case 0x3037: mapif_parse_GuildMessage(fd,RFIFOL(fd,4),RFIFOL(fd,8),RFIFOP(fd,12),RFIFOW(fd,2)-12); break; + case 0x3037: mapif_parse_GuildMessage(fd,RFIFOL(fd,4),RFIFOL(fd,8),(char*)RFIFOP(fd,12),RFIFOW(fd,2)-12); break; case 0x3038: mapif_parse_GuildCheck(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); break; - case 0x3039: mapif_parse_GuildBasicInfoChange(fd,RFIFOL(fd,4),RFIFOW(fd,8),RFIFOP(fd,10),RFIFOW(fd,2)-10); break; - case 0x303A: mapif_parse_GuildMemberInfoChange(fd,RFIFOL(fd,4),RFIFOL(fd,8),RFIFOL(fd,12),RFIFOW(fd,16),RFIFOP(fd,18),RFIFOW(fd,2)-18); break; + case 0x3039: mapif_parse_GuildBasicInfoChange(fd,RFIFOL(fd,4),RFIFOW(fd,8),(const char*)RFIFOP(fd,10),RFIFOW(fd,2)-10); break; + case 0x303A: mapif_parse_GuildMemberInfoChange(fd,RFIFOL(fd,4),RFIFOL(fd,8),RFIFOL(fd,12),RFIFOW(fd,16),(const char*)RFIFOP(fd,18),RFIFOW(fd,2)-18); break; case 0x303B: mapif_parse_GuildPosition(fd,RFIFOL(fd,4),RFIFOL(fd,8),(struct guild_position *)RFIFOP(fd,12)); break; case 0x303C: mapif_parse_GuildSkillUp(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); break; case 0x303D: mapif_parse_GuildAlliance(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18)); break; - case 0x303E: mapif_parse_GuildNotice(fd,RFIFOL(fd,2),RFIFOP(fd,6),RFIFOP(fd,66)); break; - case 0x303F: mapif_parse_GuildEmblem(fd,RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8),RFIFOP(fd,12)); break; + case 0x303E: mapif_parse_GuildNotice(fd,RFIFOL(fd,2),(const char*)RFIFOP(fd,6),(const char*)RFIFOP(fd,66)); break; + case 0x303F: mapif_parse_GuildEmblem(fd,RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8),(const char*)RFIFOP(fd,12)); break; case 0x3040: mapif_parse_GuildCastleDataLoad(fd,RFIFOW(fd,2),RFIFOB(fd,4)); break; case 0x3041: mapif_parse_GuildCastleDataSave(fd,RFIFOW(fd,2),RFIFOB(fd,4),RFIFOL(fd,5)); break; diff --git a/src/char_sql/int_guild.h b/src/char_sql/int_guild.h index 8f4203d7c..8257cf8f6 100644 --- a/src/char_sql/int_guild.h +++ b/src/char_sql/int_guild.h @@ -3,6 +3,7 @@ int inter_guild_parse_frommap(int fd); int inter_guild_sql_init(); +void inter_guild_sql_final(); int inter_guild_mapif_init(int fd); int inter_guild_leave(int guild_id,int account_id,int char_id); diff --git a/src/char_sql/int_party.c b/src/char_sql/int_party.c index b2528a42d..430385110 100644 --- a/src/char_sql/int_party.c +++ b/src/char_sql/int_party.c @@ -3,15 +3,12 @@ // SQL conversion by hack // -#include "char.h" -#include "strlib.h" -#include "socket.h" #include <stdio.h> #include <stdlib.h> #include <string.h> - - -#define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y) +#include "char.h" +#include "../common/strlib.h" +#include "socket.h" static struct party *party_pt; static int party_newid=100; @@ -20,29 +17,31 @@ int mapif_party_broken(int party_id,int flag); int party_check_empty(struct party *p); int mapif_parse_PartyLeave(int fd,int party_id,int account_id); +#define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y) + // Save party to mysql int inter_party_tosql(int party_id,struct party *p) { // 'party' ('party_id','name','exp','item','leader') - + char t_name[100]; char t_member[24]; int party_member = 0, party_online_member = 0; int party_exist = 0; int leader_id = 0; int i = 0; - + printf("(\033[1;64m%d\033[0m) Request save party - ",party_id); - + jstrescapecpy(t_name, p->name); - + if (p==NULL || party_id==0 || p->party_id ==0 || party_id!=p->party_id) { printf("- Party pointer or party_id error \n"); return 0; } - - // Check if party exists - sprintf(tmp_sql,"SELECT count(*) FROM `%s` WHERE `party_id`='%d'",party_db, party_id); + + // Check if party exists + sprintf(tmp_sql,"SELECT count(*) FROM `%s` WHERE `party_id`='%d'",party_db, party_id); // TBR if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); return 0; @@ -57,7 +56,7 @@ int inter_party_tosql(int party_id,struct party *p) if (party_exist >0){ // Check members in party - sprintf(tmp_sql,"SELECT count(*) FROM `%s` WHERE `party_id`='%d'",char_db, party_id); + sprintf(tmp_sql,"SELECT count(*) FROM `%s` WHERE `party_id`='%d'",char_db, party_id); // TBR if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); return 0; @@ -65,22 +64,22 @@ int inter_party_tosql(int party_id,struct party *p) sql_res = mysql_store_result(&mysql_handle) ; if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { sql_row = mysql_fetch_row(sql_res); - + party_member = atoi (sql_row[0]); // printf("- Check members in party %d : %d \n",party_id,party_member); } mysql_free_result(sql_res) ; //resource free - + party_online_member = 0; i=0; while (i<MAX_PARTY){ if (p->member[i].account_id>0) party_online_member++; i++; } - + //if (party_online_member==0) printf("- No member online \n"); else printf("- Some member %d online \n", party_online_member); - + if (party_member <= 0 && party_online_member == 0) { // Delete the party, if has no member. @@ -93,29 +92,29 @@ int inter_party_tosql(int party_id,struct party *p) return 0; } else { // Update party information, if exists - + int i=0; - + for (i=0;i<MAX_PARTY;i++){ if (p->member[i].account_id>0){ - sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='%d', `online`='%d' WHERE `account_id`='%d' AND `name`='%s'", - char_db, party_id, p->member[i].online, p->member[i].account_id,jstrescapecpy(t_member,p->member[i].name)); + sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `name`='%s'", + char_db, party_id, p->member[i].account_id,jstrescapecpy(t_member,p->member[i].name)); //printf("%s",tmp_sql); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle) ); } } } - - + + sprintf(tmp_sql,"UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d', `leader_id`=`leader_id` WHERE `party_id`='%d'", - party_db, t_name,p->exp,p->item,party_id); + party_db, t_name,p->exp,p->item,party_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (inset/update `party`)- %s\n", mysql_error(&mysql_handle) ); } - + // printf("- Update party %d information \n",party_id); } } else { @@ -129,18 +128,18 @@ int inter_party_tosql(int party_id,struct party *p) printf("DB server Error (inset/update `party`)- %s\n", mysql_error(&mysql_handle) ); return 0; } - - sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='%d', `online`='1' WHERE `account_id`='%d' AND `name`='%s'", - char_db, party_id,leader_id, jstrescapecpy(t_member,p->member[i].name)); + + sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `name`='%s'", + char_db, party_id,leader_id, jstrescapecpy(t_member,p->member[i].name)); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (inset/update `party`)- %s\n", mysql_error(&mysql_handle) ); } - - //printf("- Insert new party %d \n",party_id); + + //printf("- Insert new party %d \n",party_id); } - + printf("Party save success\n"); - return 0; + return 0; } @@ -149,15 +148,15 @@ int inter_party_fromsql(int party_id,struct party *p) { int leader_id=0; printf("(\033[1;64m%d\033[0m) Request load party - ",party_id); - + memset(p, 0, sizeof(struct party)); - - sprintf(tmp_sql,"SELECT `party_id`, `name`,`exp`,`item`, `leader_id` FROM `%s` WHERE `party_id`='%d'",party_db, party_id); + + sprintf(tmp_sql,"SELECT `party_id`, `name`,`exp`,`item`, `leader_id` FROM `%s` WHERE `party_id`='%d'",party_db, party_id); // TBR if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (select `party`)- %s\n", mysql_error(&mysql_handle) ); return 0; } - + sql_res = mysql_store_result(&mysql_handle) ; if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { sql_row = mysql_fetch_row(sql_res); @@ -172,11 +171,11 @@ int inter_party_fromsql(int party_id,struct party *p) // printf("- Cannot find party %d \n",party_id); return 0; } - + mysql_free_result(sql_res); - + // Load members - sprintf(tmp_sql,"SELECT `account_id`, `name`,`base_level`,`last_map`,`online` FROM `%s` WHERE `party_id`='%d'",char_db, party_id); + sprintf(tmp_sql,"SELECT `account_id`, `name`,`base_level`,`last_map`,`online` FROM `%s` WHERE `party_id`='%d'",char_db, party_id); // TBR if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (select `party`)- %s\n", mysql_error(&mysql_handle) ); return 0; @@ -196,25 +195,20 @@ int inter_party_fromsql(int party_id,struct party *p) // printf("- %d members found in party %d \n",i,party_id); } mysql_free_result(sql_res); - - + + printf("Party load success\n"); return 0; - + } int inter_party_sql_init(){ int i; - + //memory alloc printf("interserver party memory initialize.... (%d byte)\n",sizeof(struct party)); - party_pt = calloc(sizeof(struct party), 1); - - sprintf(tmp_sql,"UPDATE `%s` SET `online`='0'", char_db); - if(mysql_query(&mysql_handle, tmp_sql) ) { - printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle) ); - } - + party_pt = (struct party*)aCalloc(sizeof(struct party), 1); + sprintf (tmp_sql , "SELECT count(*) FROM `%s`",party_db); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); @@ -231,18 +225,22 @@ int inter_party_sql_init(){ if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); } - + sql_res = mysql_store_result(&mysql_handle) ; - + sql_row = mysql_fetch_row(sql_res); party_newid = atoi (sql_row[0])+1; mysql_free_result(sql_res); } - + printf("set party_newid: %d.......\n",party_newid); - + return 0; } +void inter_party_sql_final(){ + if (party_pt) aFree(party_pt); + return; +} // Search for the party according to its name @@ -251,8 +249,8 @@ struct party* search_partyname(char *str) struct party *p=NULL; int leader_id = 0; char t_name[24]; - - sprintf(tmp_sql,"SELECT `party_id`, `name`,`exp`,`item`,`leader_id` FROM `%s` WHERE `name`='%s'",party_db, jstrescapecpy(t_name,str)); + + sprintf(tmp_sql,"SELECT `party_id`, `name`,`exp`,`item`,`leader_id` FROM `%s` WHERE `name`='%s'",party_db, jstrescapecpy(t_name,str)); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (select `party`)- %s\n", mysql_error(&mysql_handle) ); } @@ -295,16 +293,32 @@ struct party* search_partyname(char *str) // EXPŒö•½•ª”z‚Å‚«‚é‚©ƒ`ƒFƒbƒN int party_check_exp_share(struct party *p) { - int i; - int maxlv=0,minlv=0x7fffffff; - for(i=0;i<MAX_PARTY;i++){ - int lv=p->member[i].lv; - if( p->member[i].online ){ - if( lv < minlv ) minlv=lv; - if( maxlv < lv ) maxlv=lv; - } - } - return (maxlv==0 || maxlv-minlv<=party_share_level); + int i, dudes=0; + int pl1=0,pl2=0,pl3=0; + int maxlv=0,minlv=0x7fffffff; + for(i=0;i<MAX_PARTY;i++){ + int lv=p->member[i].lv; + if (!lv) continue; + if( p->member[i].online ){ + if( lv < minlv ) minlv=lv; + if( maxlv < lv ) maxlv=lv; + if( lv >= 70 ) dudes+=1000; + dudes++; + } + } + if((dudes/1000 >= 2) && (dudes%1000 == 3) && (!strcmp(p->member[0].map,p->member[1].map)) && (!strcmp(p->member[1].map,p->member[2].map))) { + pl1=char_nick2id(p->member[0].name); + pl2=char_nick2id(p->member[1].name); + pl3=char_nick2id(p->member[2].name); + printf("PARTY: group of 3 Id1 %d lv %d name %s Id2 %d lv %d name %s Id3 %d lv %d name %s\n",pl1,p->member[0].lv,p->member[0].name,pl2,p->member[1].lv,p->member[1].name,pl3,p->member[2].lv,p->member[2].name); + if (char_married(pl1,pl2) && char_child(pl1,pl3)) + return 1; + if (char_married(pl1,pl3) && char_child(pl1,pl2)) + return 1; + if (char_married(pl2,pl3) && char_child(pl2,pl1)) + return 1; + } + return (maxlv==0 || maxlv-minlv<=party_share_level); } // Is there any member in the party? int party_check_empty(struct party *p) @@ -441,7 +455,7 @@ int mapif_party_broken(int party_id,int flag) return 0; } // ƒp[ƒeƒB“à”Œ¾ -int mapif_party_message(int party_id,int account_id,char *mes,int len) +int mapif_party_message(int party_id,int account_id,char *mes,int len, int sfd) { unsigned char buf[512]; WBUFW(buf,0)=0x3827; @@ -449,7 +463,7 @@ int mapif_party_message(int party_id,int account_id,char *mes,int len) WBUFL(buf,4)=party_id; WBUFL(buf,8)=account_id; memcpy(WBUFP(buf,12),mes,len); - mapif_sendall(buf,len+12); + mapif_sendallwos(sfd, buf,len+12); return 0; } @@ -458,7 +472,7 @@ int mapif_party_message(int party_id,int account_id,char *mes,int len) // Create Party -int mapif_parse_CreateParty(int fd,int account_id,char *name,char *nick,char *map,int lv) +int mapif_parse_CreateParty(int fd,int account_id,char *name,char *nick,char *map,int lv, int item, int item2) { struct party *p; if( (p=search_partyname(name))!=NULL){ @@ -476,19 +490,24 @@ int mapif_parse_CreateParty(int fd,int account_id,char *name,char *nick,char *ma p->party_id=party_newid++; memcpy(p->name,name,24); p->exp=0; - p->item=0; + p->item=item; + //<item1>ƒAƒCƒeƒ€?W•û–@B0‚ÅŒÂl•ÊA1‚Ńp?ƒeƒBŒö—L + //<item2>ƒAƒCƒeƒ€•ª”z•û–@B0‚ÅŒÂl•ÊA1‚Ńp?ƒeƒB‚ɋϓ™•ª”z + //difference between "collection" and "distribution" is...? ^^; + p->itemc = 0; + p->member[0].account_id=account_id; memcpy(p->member[0].name,nick,24); memcpy(p->member[0].map,map,16); p->member[0].leader=1; p->member[0].online=1; p->member[0].lv=lv; - + inter_party_tosql(p->party_id,p); - + mapif_party_created(fd,account_id,p); mapif_party_info(fd,p); - + return 0; } // ƒp[ƒeƒBî•ñ—v‹ @@ -500,7 +519,7 @@ int mapif_parse_PartyInfo(int fd,int party_id) return 0; } inter_party_fromsql(party_id, p); - + if(p->party_id >= 0) mapif_party_info(fd,p); else @@ -512,23 +531,23 @@ int mapif_parse_PartyAddMember(int fd,int party_id,int account_id,char *nick,cha { struct party *p; int i; - + p = party_pt; if(p==NULL){ printf("int_party: out of memory !\n"); return 0; } inter_party_fromsql(party_id, p); - + if(p->party_id <= 0){ mapif_party_memberadded(fd,party_id,account_id,1); return 0; } - + for(i=0;i<MAX_PARTY;i++){ if(p->member[i].account_id==0){ int flag=0; - + p->member[i].account_id=account_id; memcpy(p->member[i].name,nick,24); memcpy(p->member[i].map,map,16); @@ -544,7 +563,7 @@ int mapif_parse_PartyAddMember(int fd,int party_id,int account_id,char *nick,cha } if(flag) mapif_party_optionchanged(fd,p,0,0); - + inter_party_tosql(party_id, p); return 0; } @@ -558,25 +577,25 @@ int mapif_parse_PartyChangeOption(int fd,int party_id,int account_id,int exp,int { struct party *p; int flag=0; - + p = party_pt; if(p==NULL){ printf("int_party: out of memory !\n"); return 0; } - + inter_party_fromsql(party_id, p); - + if(p->party_id <= 0){ return 0; } - + p->exp=exp; if( exp>0 && !party_check_exp_share(p) ){ flag|=0x01; p->exp=0; } - + p->item=item; mapif_party_optionchanged(fd,p,account_id,flag); @@ -592,27 +611,27 @@ int mapif_parse_PartyLeave(int fd,int party_id,int account_id) printf("int_party: out of memory !\n"); return 0; } - + inter_party_fromsql(party_id, p); - + if(p->party_id >= 0){ int i,j; for(i=0;i<MAX_PARTY;i++){ - + if(p->member[i].account_id==account_id){ //printf("p->member[i].account_id = %d , account_id = %d \n",p->member[i].account_id,account_id); mapif_party_leaved(party_id,account_id,p->member[i].name); - - - + + + // Update char information, does the name need encoding? - sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='0', `online`='1' WHERE `party_id`='%d' AND `name`='%s'", + sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `name`='%s'", char_db, party_id, jstrescapecpy(t_member,p->member[i].name)); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle) ); } -// printf("Delete member %s from MySQL \n", p->member[i].name); - +// printf("Delete member %s from MySQL \n", p->member[i].name); + if (p->member[i].leader==1){ for(j=0;j<MAX_PARTY;j++) { @@ -620,12 +639,12 @@ int mapif_parse_PartyLeave(int fd,int party_id,int account_id) if(p->member[j].account_id>0&&j!=i){ mapif_party_leaved(party_id,p->member[j].account_id,p->member[j].name); // Update char information, does the name need encoding? - sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='0', `online`='1' WHERE `party_id`='%d' AND `name`='%s'", + sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `name`='%s'", char_db, party_id, jstrescapecpy(t_member,p->member[i].name)); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle) ); } -// printf("Delete member %s from MySQL \n", p->member[j].name); +// printf("Delete member %s from MySQL \n", p->member[j].name); } } // Delete the party, if has no member. @@ -634,9 +653,9 @@ int mapif_parse_PartyLeave(int fd,int party_id,int account_id) printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); } // printf("Leader breaks party %d \n",party_id); - memset(p, 0, sizeof(struct party)); + memset(p, 0, sizeof(struct party)); }else memset(&p->member[i],0,sizeof(struct party_member)); - + break; } @@ -648,8 +667,8 @@ int mapif_parse_PartyLeave(int fd,int party_id,int account_id) inter_party_tosql(party_id,p); // Break the party if no member */ }else{ - sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `online`='1'", - char_db, party_id, account_id); + sprintf(tmp_sql,"UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `online`='1'", + char_db, party_id, account_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle) ); } @@ -661,21 +680,21 @@ int mapif_parse_PartyChangeMap(int fd,int party_id,int account_id,char *map,int { struct party *p; int i; - + p = party_pt; if(p==NULL){ printf("int_party: out of memory !\n"); return 0; } inter_party_fromsql(party_id, p); - + if(p->party_id <= 0){ return 0; } for(i=0;i<MAX_PARTY;i++){ if(p->member[i].account_id==account_id){ int flag=0; - + memcpy(p->member[i].map,map,16); p->member[i].online=online; p->member[i].lv=lv; @@ -697,27 +716,27 @@ int mapif_parse_PartyChangeMap(int fd,int party_id,int account_id,char *map,int int mapif_parse_BreakParty(int fd,int party_id) { struct party *p; - + p = party_pt; if(p==NULL){ printf("int_party: out of memory !\n"); return 0; } - + inter_party_fromsql(party_id, p); - + if(p->party_id <= 0){ return 0; } inter_party_tosql(party_id,p); - + mapif_party_broken(fd,party_id); return 0; } // ƒp[ƒeƒBƒƒbƒZ[ƒW‘—M int mapif_parse_PartyMessage(int fd,int party_id,int account_id,char *mes,int len) { - return mapif_party_message(party_id,account_id,mes,len); + return mapif_party_message(party_id,account_id,mes,len, fd); } // ƒp[ƒeƒBƒ`ƒFƒbƒN—v‹ int mapif_parse_PartyCheck(int fd,int party_id,int account_id,char *nick) @@ -733,15 +752,15 @@ int mapif_parse_PartyCheck(int fd,int party_id,int account_id,char *nick) int inter_party_parse_frommap(int fd) { switch(RFIFOW(fd,0)){ - case 0x3020: mapif_parse_CreateParty(fd,RFIFOL(fd,2),RFIFOP(fd,6),RFIFOP(fd,30),RFIFOP(fd,54),RFIFOW(fd,70)); break; + case 0x3020: mapif_parse_CreateParty(fd,RFIFOL(fd,2),(char*)RFIFOP(fd,6),(char*)RFIFOP(fd,30),(char*)RFIFOP(fd,54),RFIFOW(fd,70), RFIFOB(fd,72), RFIFOB(fd,73)); break; case 0x3021: mapif_parse_PartyInfo(fd,RFIFOL(fd,2)); break; - case 0x3022: mapif_parse_PartyAddMember(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10),RFIFOP(fd,34),RFIFOW(fd,50)); break; + case 0x3022: mapif_parse_PartyAddMember(fd,RFIFOL(fd,2),RFIFOL(fd,6),(char*)RFIFOP(fd,10),(char*)RFIFOP(fd,34),RFIFOW(fd,50)); break; case 0x3023: mapif_parse_PartyChangeOption(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOW(fd,10),RFIFOW(fd,12)); break; case 0x3024: mapif_parse_PartyLeave(fd,RFIFOL(fd,2),RFIFOL(fd,6)); break; - case 0x3025: mapif_parse_PartyChangeMap(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27)); break; + case 0x3025: mapif_parse_PartyChangeMap(fd,RFIFOL(fd,2),RFIFOL(fd,6),(char*)RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27)); break; case 0x3026: mapif_parse_BreakParty(fd,RFIFOL(fd,2)); break; - case 0x3027: mapif_parse_PartyMessage(fd,RFIFOL(fd,4),RFIFOL(fd,8),RFIFOP(fd,12),RFIFOW(fd,2)-12); break; - case 0x3028: mapif_parse_PartyCheck(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10)); break; + case 0x3027: mapif_parse_PartyMessage(fd,RFIFOL(fd,4),RFIFOL(fd,8),(char*)RFIFOP(fd,12),RFIFOW(fd,2)-12); break; + case 0x3028: mapif_parse_PartyCheck(fd,RFIFOL(fd,2),RFIFOL(fd,6),(char*)RFIFOP(fd,10)); break; default: return 0; } diff --git a/src/char_sql/int_party.h b/src/char_sql/int_party.h index 04f71c881..686d70b04 100644 --- a/src/char_sql/int_party.h +++ b/src/char_sql/int_party.h @@ -3,6 +3,7 @@ int inter_party_parse_frommap(int fd); int inter_party_sql_init(); +void inter_party_sql_final(); int inter_party_leave(int party_id,int account_id); #endif diff --git a/src/char_sql/int_pet.c b/src/char_sql/int_pet.c index 7f2ed2a7c..ea1fed67d 100644 --- a/src/char_sql/int_pet.c +++ b/src/char_sql/int_pet.c @@ -2,13 +2,13 @@ // original code from athena // SQL conversion by Jioh L. Jung // -#include "char.h" -#include "strlib.h" - #include <stdio.h> #include <stdlib.h> #include <string.h> +#include "char.h" +#include "../common/strlib.h" + struct s_pet *pet_pt; static int pet_newid = 100; @@ -18,11 +18,11 @@ static int pet_newid = 100; int inter_pet_tosql(int pet_id, struct s_pet *p) { //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) char t_name[100]; - + printf("request save pet: %d.......\n",pet_id); - + jstrescapecpy(t_name, p->name); - + if(p->hungry < 0) p->hungry = 0; else if(p->hungry > 100) @@ -36,32 +36,32 @@ int inter_pet_tosql(int pet_id, struct s_pet *p) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); } sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res!=NULL && mysql_num_rows(sql_res)>0) + if (sql_res!=NULL && mysql_num_rows(sql_res)>0) //row reside -> updating sprintf(tmp_sql, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incuvate`='%d' WHERE `pet_id`='%d'", - pet_db, p->class, t_name, p->account_id, p->char_id, p->level, p->egg_id, + pet_db, p->class_, t_name, p->account_id, p->char_id, p->level, p->egg_id, p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate, p->pet_id); else //no row -> insert sprintf(tmp_sql,"INSERT INTO `%s` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) VALUES ('%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - pet_db, pet_id, p->class, t_name, p->account_id, p->char_id, p->level, p->egg_id, + pet_db, pet_id, p->class_, t_name, p->account_id, p->char_id, p->level, p->egg_id, p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate); mysql_free_result(sql_res) ; //resource free if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (inset/update `pet`)- %s\n", mysql_error(&mysql_handle) ); } - + printf("pet save success.......\n"); return 0; } int inter_pet_fromsql(int pet_id, struct s_pet *p){ - + printf("request load pet: %d.......\n",pet_id); - + memset(p, 0, sizeof(struct s_pet)); - + //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) - + sprintf(tmp_sql,"SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate` FROM `%s` WHERE `pet_id`='%d'",pet_db, pet_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (select `pet`)- %s\n", mysql_error(&mysql_handle) ); @@ -70,9 +70,9 @@ int inter_pet_fromsql(int pet_id, struct s_pet *p){ sql_res = mysql_store_result(&mysql_handle) ; if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { sql_row = mysql_fetch_row(sql_res); - + p->pet_id = pet_id; - p->class = atoi(sql_row[1]); + p->class_ = atoi(sql_row[1]); memcpy(p->name, sql_row[2],24); p->account_id = atoi(sql_row[3]); p->char_id = atoi(sql_row[4]); @@ -92,20 +92,20 @@ int inter_pet_fromsql(int pet_id, struct s_pet *p){ p->intimate = 0; else if(p->intimate > 1000) p->intimate = 1000; - + mysql_free_result(sql_res); - + printf("pet load success.......\n"); return 0; } //---------------------------------------------- - + int inter_pet_sql_init(){ int i; - + //memory alloc printf("interserver pet memory initialize.... (%d byte)\n",sizeof(struct s_pet)); - pet_pt = calloc(sizeof(struct s_pet), 1); + pet_pt = (struct s_pet*)aCalloc(sizeof(struct s_pet), 1); sprintf (tmp_sql , "SELECT count(*) FROM `%s`", pet_db); if(mysql_query(&mysql_handle, tmp_sql) ) { @@ -124,22 +124,26 @@ int inter_pet_sql_init(){ if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); } - + sql_res = mysql_store_result(&mysql_handle) ; - + sql_row = mysql_fetch_row(sql_res); pet_newid = atoi (sql_row[0])+1; //should SET MAX existing PET ID + 1 [Lupus] mysql_free_result(sql_res); } - + printf("set pet_newid: %d.......\n",pet_newid); - + return 0; } +void inter_pet_sql_final(){ + if (pet_pt) aFree(pet_pt); + return; +} //---------------------------------- int inter_pet_delete(int pet_id){ printf("request delete pet: %d.......\n",pet_id); - + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `pet_id`='%d'",pet_db, pet_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); @@ -215,7 +219,7 @@ int mapif_create_pet(int fd, int account_id, int char_id, short pet_class, short pet_pt->account_id = account_id; pet_pt->char_id = char_id; } - pet_pt->class = pet_class; + pet_pt->class_ = pet_class; pet_pt->level = pet_lv; pet_pt->egg_id = pet_egg_id; pet_pt->equip = pet_equip; @@ -232,19 +236,19 @@ int mapif_create_pet(int fd, int account_id, int char_id, short pet_class, short pet_pt->intimate = 0; else if(pet_pt->intimate > 1000) pet_pt->intimate = 1000; - + inter_pet_tosql(pet_pt->pet_id,pet_pt); - + mapif_pet_created(fd, account_id, pet_pt); - + return 0; } int mapif_load_pet(int fd, int account_id, int char_id, int pet_id){ memset(pet_pt, 0, sizeof(struct s_pet)); - + inter_pet_fromsql(pet_id, pet_pt); - + if(pet_pt!=NULL) { if(pet_pt->incuvate == 1) { pet_pt->account_id = pet_pt->char_id = 0; @@ -267,7 +271,7 @@ int mapif_save_pet(int fd, int account_id, struct s_pet *data) { if(sizeof(struct s_pet)!=len-8) { printf("inter pet: data size error %d %d\n", sizeof(struct s_pet), len-8); } - + else{ if(data->hungry < 0) data->hungry = 0; @@ -292,7 +296,7 @@ int mapif_delete_pet(int fd, int pet_id){ int mapif_parse_CreatePet(int fd){ mapif_create_pet(fd, RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOW(fd, 10), RFIFOW(fd, 12), RFIFOW(fd, 14), RFIFOW(fd, 16), RFIFOL(fd, 18), - RFIFOL(fd, 20), RFIFOB(fd, 22), RFIFOB(fd, 23), RFIFOP(fd, 24)); + RFIFOL(fd, 20), RFIFOB(fd, 22), RFIFOB(fd, 23), (char*)RFIFOP(fd, 24)); return 0; } diff --git a/src/char_sql/int_pet.h b/src/char_sql/int_pet.h index b6e3f1bbf..39f127262 100644 --- a/src/char_sql/int_pet.h +++ b/src/char_sql/int_pet.h @@ -2,6 +2,7 @@ #define _INT_PET_H_ int inter_pet_init(); +void inter_pet_sql_final(); int inter_pet_save(); int inter_pet_delete(int pet_id); diff --git a/src/char_sql/int_storage.c b/src/char_sql/int_storage.c index 18100e02a..c13c782a6 100644 --- a/src/char_sql/int_storage.c +++ b/src/char_sql/int_storage.c @@ -2,62 +2,46 @@ // original code from athena // SQL conversion by Jioh L. Jung // -#include "char.h" -#include "itemdb.h" #include <string.h> #include <stdlib.h> +#include "char.h" +#include "itemdb.h" + #define STORAGE_MEMINC 16 // reset by inter_config_read() struct storage *storage_pt=NULL; struct guild_storage *guild_storage_pt=NULL; - #define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y) // storage data -> DB conversion int storage_tosql(int account_id,struct storage *p){ int i; - int eqcount=1; - int noteqcount=1; - struct itemtemp mapitem; +// int eqcount=1; +// int noteqcount=1; + int count=0; + struct itemtmp mapitem[MAX_GUILD_STORAGE]; for(i=0;i<MAX_STORAGE;i++){ - if(p->storage[i].nameid>0){ - if(itemdb_isequip(p->storage[i].nameid)==1){ - mapitem.equip[eqcount].flag=0; - mapitem.equip[eqcount].id = p->storage[i].id; - mapitem.equip[eqcount].nameid=p->storage[i].nameid; - mapitem.equip[eqcount].amount = p->storage[i].amount; - mapitem.equip[eqcount].equip = p->storage[i].equip; - mapitem.equip[eqcount].identify = p->storage[i].identify; - mapitem.equip[eqcount].refine = p->storage[i].refine; - mapitem.equip[eqcount].attribute = p->storage[i].attribute; - mapitem.equip[eqcount].card[0] = p->storage[i].card[0]; - mapitem.equip[eqcount].card[1] = p->storage[i].card[1]; - mapitem.equip[eqcount].card[2] = p->storage[i].card[2]; - mapitem.equip[eqcount].card[3] = p->storage[i].card[3]; - eqcount++; - } - else if(itemdb_isequip(p->storage[i].nameid)==0){ - mapitem.notequip[noteqcount].flag=0; - mapitem.notequip[noteqcount].id = p->storage[i].id; - mapitem.notequip[noteqcount].nameid=p->storage[i].nameid; - mapitem.notequip[noteqcount].amount = p->storage[i].amount; - mapitem.notequip[noteqcount].equip = p->storage[i].equip; - mapitem.notequip[noteqcount].identify = p->storage[i].identify; - mapitem.notequip[noteqcount].refine = p->storage[i].refine; - mapitem.notequip[noteqcount].attribute = p->storage[i].attribute; - mapitem.notequip[noteqcount].card[0] = p->storage[i].card[0]; - mapitem.notequip[noteqcount].card[1] = p->storage[i].card[1]; - mapitem.notequip[noteqcount].card[2] = p->storage[i].card[2]; - mapitem.notequip[noteqcount].card[3] = p->storage[i].card[3]; - noteqcount++; - } + if(p->storage_[i].nameid>0){ + mapitem[count].flag=0; + mapitem[count].id = p->storage_[i].id; + mapitem[count].nameid=p->storage_[i].nameid; + mapitem[count].amount = p->storage_[i].amount; + mapitem[count].equip = p->storage_[i].equip; + mapitem[count].identify = p->storage_[i].identify; + mapitem[count].refine = p->storage_[i].refine; + mapitem[count].attribute = p->storage_[i].attribute; + mapitem[count].card[0] = p->storage_[i].card[0]; + mapitem[count].card[1] = p->storage_[i].card[1]; + mapitem[count].card[2] = p->storage_[i].card[2]; + mapitem[count].card[3] = p->storage_[i].card[3]; + count++; } } - memitemdata_to_sql(mapitem, eqcount, noteqcount, account_id,TABLE_STORAGE); + memitemdata_to_sql(mapitem, count, account_id,TABLE_STORAGE); //printf ("storage dump to DB - id: %d (total: %d)\n", account_id, j); return 0; @@ -66,36 +50,36 @@ int storage_tosql(int account_id,struct storage *p){ // DB -> storage data conversion int storage_fromsql(int account_id, struct storage *p){ int i=0; - + memset(p,0,sizeof(struct storage)); //clean up memory p->storage_amount = 0; p->account_id = account_id; - + // storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`} sprintf(tmp_sql,"SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`card0`,`card1`,`card2`,`card3` FROM `%s` WHERE `account_id`='%d'",storage_db, account_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); } sql_res = mysql_store_result(&mysql_handle) ; - + if (sql_res) { while((sql_row = mysql_fetch_row(sql_res))) { //start to fetch - p->storage[i].id= atoi(sql_row[0]); - p->storage[i].nameid= atoi(sql_row[1]); - p->storage[i].amount= atoi(sql_row[2]); - p->storage[i].equip= atoi(sql_row[3]); - p->storage[i].identify= atoi(sql_row[4]); - p->storage[i].refine= atoi(sql_row[5]); - p->storage[i].attribute= atoi(sql_row[6]); - p->storage[i].card[0]= atoi(sql_row[7]); - p->storage[i].card[1]= atoi(sql_row[8]); - p->storage[i].card[2]= atoi(sql_row[9]); - p->storage[i].card[3]= atoi(sql_row[10]); + p->storage_[i].id= atoi(sql_row[0]); + p->storage_[i].nameid= atoi(sql_row[1]); + p->storage_[i].amount= atoi(sql_row[2]); + p->storage_[i].equip= atoi(sql_row[3]); + p->storage_[i].identify= atoi(sql_row[4]); + p->storage_[i].refine= atoi(sql_row[5]); + p->storage_[i].attribute= atoi(sql_row[6]); + p->storage_[i].card[0]= atoi(sql_row[7]); + p->storage_[i].card[1]= atoi(sql_row[8]); + p->storage_[i].card[2]= atoi(sql_row[9]); + p->storage_[i].card[3]= atoi(sql_row[10]); p->storage_amount = ++i; } mysql_free_result(sql_res); } - + printf ("storage load complete from DB - id: %d (total: %d)\n", account_id, p->storage_amount); return 1; } @@ -103,45 +87,29 @@ int storage_fromsql(int account_id, struct storage *p){ // Save guild_storage data to sql int guild_storage_tosql(int guild_id, struct guild_storage *p){ int i; - int eqcount=1; - int noteqcount=1; - struct itemtemp mapitem; +// int eqcount=1; +// int noteqcount=1; + int count=0; + struct itemtmp mapitem[MAX_GUILD_STORAGE]; for(i=0;i<MAX_GUILD_STORAGE;i++){ - if(p->storage[i].nameid>0){ - if(itemdb_isequip(p->storage[i].nameid)==1){ - mapitem.equip[eqcount].flag=0; - mapitem.equip[eqcount].id = p->storage[i].id; - mapitem.equip[eqcount].nameid=p->storage[i].nameid; - mapitem.equip[eqcount].amount = p->storage[i].amount; - mapitem.equip[eqcount].equip = p->storage[i].equip; - mapitem.equip[eqcount].identify = p->storage[i].identify; - mapitem.equip[eqcount].refine = p->storage[i].refine; - mapitem.equip[eqcount].attribute = p->storage[i].attribute; - mapitem.equip[eqcount].card[0] = p->storage[i].card[0]; - mapitem.equip[eqcount].card[1] = p->storage[i].card[1]; - mapitem.equip[eqcount].card[2] = p->storage[i].card[2]; - mapitem.equip[eqcount].card[3] = p->storage[i].card[3]; - eqcount++; - } - else if(itemdb_isequip(p->storage[i].nameid)==0){ - mapitem.notequip[noteqcount].flag=0; - mapitem.notequip[noteqcount].id = p->storage[i].id; - mapitem.notequip[noteqcount].nameid=p->storage[i].nameid; - mapitem.notequip[noteqcount].amount = p->storage[i].amount; - mapitem.notequip[noteqcount].equip = p->storage[i].equip; - mapitem.notequip[noteqcount].identify = p->storage[i].identify; - mapitem.notequip[noteqcount].refine = p->storage[i].refine; - mapitem.notequip[noteqcount].attribute = p->storage[i].attribute; - mapitem.notequip[noteqcount].card[0] = p->storage[i].card[0]; - mapitem.notequip[noteqcount].card[1] = p->storage[i].card[1]; - mapitem.notequip[noteqcount].card[2] = p->storage[i].card[2]; - mapitem.notequip[noteqcount].card[3] = p->storage[i].card[3]; - noteqcount++; - } + if(p->storage_[i].nameid>0){ + mapitem[count].flag=0; + mapitem[count].id = p->storage_[i].id; + mapitem[count].nameid=p->storage_[i].nameid; + mapitem[count].amount = p->storage_[i].amount; + mapitem[count].equip = p->storage_[i].equip; + mapitem[count].identify = p->storage_[i].identify; + mapitem[count].refine = p->storage_[i].refine; + mapitem[count].attribute = p->storage_[i].attribute; + mapitem[count].card[0] = p->storage_[i].card[0]; + mapitem[count].card[1] = p->storage_[i].card[1]; + mapitem[count].card[2] = p->storage_[i].card[2]; + mapitem[count].card[3] = p->storage_[i].card[3]; + count++; } } - memitemdata_to_sql(mapitem, eqcount, noteqcount, guild_id,TABLE_GUILD_STORAGE); + memitemdata_to_sql(mapitem, count, guild_id,TABLE_GUILD_STORAGE); printf ("guild storage save to DB - id: %d (total: %d)\n", guild_id,i); return 0; @@ -163,21 +131,23 @@ int guild_storage_fromsql(int guild_id, struct guild_storage *p){ printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); } sql_res = mysql_store_result(&mysql_handle) ; - + if (sql_res) { while((sql_row = mysql_fetch_row(sql_res))) { //start to fetch - p->storage[i].id= atoi(sql_row[0]); - p->storage[i].nameid= atoi(sql_row[1]); - p->storage[i].amount= atoi(sql_row[2]); - p->storage[i].equip= atoi(sql_row[3]); - p->storage[i].identify= atoi(sql_row[4]); - p->storage[i].refine= atoi(sql_row[5]); - p->storage[i].attribute= atoi(sql_row[6]); - p->storage[i].card[0]= atoi(sql_row[7]); - p->storage[i].card[1]= atoi(sql_row[8]); - p->storage[i].card[2]= atoi(sql_row[9]); - p->storage[i].card[3]= atoi(sql_row[10]); + p->storage_[i].id= atoi(sql_row[0]); + p->storage_[i].nameid= atoi(sql_row[1]); + p->storage_[i].amount= atoi(sql_row[2]); + p->storage_[i].equip= atoi(sql_row[3]); + p->storage_[i].identify= atoi(sql_row[4]); + p->storage_[i].refine= atoi(sql_row[5]); + p->storage_[i].attribute= atoi(sql_row[6]); + p->storage_[i].card[0]= atoi(sql_row[7]); + p->storage_[i].card[1]= atoi(sql_row[8]); + p->storage_[i].card[2]= atoi(sql_row[9]); + p->storage_[i].card[3]= atoi(sql_row[10]); p->storage_amount = ++i; + if (i >= MAX_GUILD_STORAGE) + break; } mysql_free_result(sql_res); } @@ -188,17 +158,24 @@ int guild_storage_fromsql(int guild_id, struct guild_storage *p){ //--------------------------------------------------------- // storage data initialize int inter_storage_sql_init(){ - + //memory alloc printf("interserver storage memory initialize....(%d byte)\n",sizeof(struct storage)); - storage_pt=calloc(sizeof(struct storage), 1); - guild_storage_pt=calloc(sizeof(struct guild_storage), 1); + storage_pt = (struct storage*)aCalloc(sizeof(struct storage), 1); + guild_storage_pt = (struct guild_storage*)aCalloc(sizeof(struct guild_storage), 1); memset(storage_pt,0,sizeof(struct storage)); memset(guild_storage_pt,0,sizeof(struct guild_storage)); - + return 1; } -// ‘qŒÉƒf[ƒ^íœ +// storage data finalize +void inter_storage_sql_final() +{ + if (storage_pt) aFree(storage_pt); + if (guild_storage_pt) aFree(guild_storage_pt); + return; +} +// q?f[^? int inter_storage_delete(int account_id) { sprintf(tmp_sql, "DELETE FROM `%s` WHERE `account_id`='%d'",storage_db, account_id); @@ -243,7 +220,7 @@ int mapif_load_guild_storage(int fd,int account_id,int guild_id) { int guild_exist=0; WFIFOW(fd,0)=0x3818; - + // Check if guild exists, I may write a function for this later, coz I use it several times. //printf("- Check if guild %d exists\n",g->guild_id); sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `guild_id`='%d'",guild_db, guild_id); @@ -257,7 +234,7 @@ int mapif_load_guild_storage(int fd,int account_id,int guild_id) //printf("- Check if guild %d exists : %s\n",g->guild_id,((guild_exist==0)?"No":"Yes")); } mysql_free_result(sql_res) ; //resource free - + if(guild_exist==1) { guild_storage_fromsql(guild_id,guild_storage_pt); WFIFOW(fd,2)=sizeof(struct guild_storage)+12; @@ -296,7 +273,7 @@ int mapif_parse_LoadStorage(int fd){ int mapif_parse_SaveStorage(int fd){ int account_id=RFIFOL(fd,4); int len=RFIFOW(fd,2); - + if(sizeof(struct storage)!=len-8){ printf("inter storage: data size error %d %d\n",sizeof(struct storage),len-8); }else{ @@ -335,7 +312,7 @@ int mapif_parse_SaveGuildStorage(int fd) //printf("- Check if guild %d exists : %s\n",g->guild_id,((guild_exist==0)?"No":"Yes")); } mysql_free_result(sql_res) ; //resource free - + if(guild_exist==1) { memcpy(guild_storage_pt,RFIFOP(fd,12),sizeof(struct guild_storage)); guild_storage_tosql(guild_id,guild_storage_pt); diff --git a/src/char_sql/int_storage.h b/src/char_sql/int_storage.h index f9f37db3e..5541d1ed7 100644 --- a/src/char_sql/int_storage.h +++ b/src/char_sql/int_storage.h @@ -2,6 +2,7 @@ #define _INT_STORAGE_H_ int inter_storage_sql_init(); +void inter_storage_sql_final(); int inter_storage_delete(int account_id); int inter_guild_storage_delete(int guild_id); diff --git a/src/char_sql/inter.c b/src/char_sql/inter.c index b50afb9d7..83fcc967f 100644 --- a/src/char_sql/inter.c +++ b/src/char_sql/inter.c @@ -7,7 +7,7 @@ #include <stdlib.h> #include "char.h" -#include "strlib.h" +#include "../common/strlib.h" #include "inter.h" #include "int_party.h" #include "int_guild.h" @@ -15,8 +15,6 @@ #include "int_pet.h" #include "lock.h" -#define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y) - #define WISDATA_TTL (60*1000) // Wisƒf[ƒ^‚̶‘¶ŽžŠÔ(60•b) #define WISDELLIST_MAX 256 // Wisƒf[ƒ^íœƒŠƒXƒg‚Ì—v‘f” @@ -36,6 +34,11 @@ MYSQL_ROW sql_row ; int sql_fields, sql_cnt; char tmp_sql[65535]; +MYSQL lmysql_handle; +char tmp_lsql[65535]; +MYSQL_RES* lsql_res ; +MYSQL_ROW lsql_row ; + int char_server_port = 3306; char char_server_ip[32] = "127.0.0.1"; char char_server_id[32] = "ragnarok"; @@ -64,7 +67,7 @@ int inter_send_packet_length[]={ int inter_recv_packet_length[]={ -1,-1, 7, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, - 72, 6,52,14, 10,29, 6,-1, 34, 0, 0, 0, 0, 0, 0, 0, + 74, 6,52,14, 10,29, 6,-1, 34, 0, 0, 0, 0, 0, 0, 0, -1, 6,-1, 0, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1, 5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -84,20 +87,20 @@ static int wis_dellist[WISDELLIST_MAX], wis_delnum; //-------------------------------------------------------- // Save account_reg to sql (type=2) int inter_accreg_tosql(int account_id,struct accreg *reg){ - + int j; char temp_str[32]; if (account_id<=0) return 0; reg->account_id=account_id; - + //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=2 AND `account_id`='%d'",reg_db, account_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (delete `global_reg_value`)- %s\n", mysql_error(&mysql_handle) ); } - + if (reg->reg_num<=0) return 0; - + for(j=0;j<reg->reg_num;j++){ if(reg->reg[j].str != NULL){ sprintf(tmp_sql,"INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES (2,'%d', '%s','%d')", @@ -117,7 +120,7 @@ int inter_accreg_fromsql(int account_id,struct accreg *reg) if (reg==NULL) return 0; memset(reg, 0, sizeof(struct accreg)); reg->account_id=account_id; - + //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) sprintf (tmp_sql, "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'",reg_db, reg->account_id); if(mysql_query(&mysql_handle, tmp_sql) ) { @@ -126,7 +129,7 @@ int inter_accreg_fromsql(int account_id,struct accreg *reg) sql_res = mysql_store_result(&mysql_handle); if (sql_res) { - for(j=0;(sql_row = mysql_fetch_row(sql_res));j++){ + for(j=0;(sql_row = mysql_fetch_row(sql_res));j++){ memcpy(reg->reg[j].str, sql_row[0],32); reg->reg[j].value = atoi(sql_row[1]); } @@ -141,7 +144,7 @@ int inter_accreg_sql_init() { CREATE(accreg_pt, struct accreg, 1); return 0; - + } /*========================================== @@ -187,7 +190,7 @@ int inter_config_read(const char *cfgName) { } //Logins information to be read from the inter_athena.conf //for character deletion (checks email in the loginDB) - + else if(strcmpi(w1,"login_server_ip")==0){ strcpy(login_server_ip, w2); printf ("set login_server_ip : %s\n",w2); @@ -223,7 +226,7 @@ int inter_config_read(const char *cfgName) { } } fclose(fp); - + printf ("success reading interserver configuration\n"); return 0; @@ -241,7 +244,7 @@ int inter_log(char *fmt,...) sprintf(tmp_sql,"INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')",interlog_db, jstrescapecpy(temp_str,str)); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (insert `interlog`)- %s\n", mysql_error(&mysql_handle) ); - } + } va_end(ap); return 0; @@ -252,37 +255,67 @@ int inter_log(char *fmt,...) int inter_init(const char *file) { //int i; - + printf ("interserver initialize...\n"); inter_config_read(file); - + //DB connection initialized mysql_init(&mysql_handle); - printf("Connect to DB server....\n"); + printf("Connect Character DB server.... (Character Server)\n"); if(!mysql_real_connect(&mysql_handle, char_server_ip, char_server_id, char_server_pw, - char_server_db ,char_server_port, (char *)NULL, CLIENT_MULTI_STATEMENTS)) { + char_server_db ,char_server_port, (char *)NULL, 0)) { //pointer check printf("%s\n",mysql_error(&mysql_handle)); exit(1); } else { - printf ("Connect Success!\n"); + printf ("Connect Success! (Character Server)\n"); + } + + mysql_init(&lmysql_handle); + printf("Connect Character DB server.... (login server)\n"); + if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw, + login_server_db ,login_server_port, (char *)NULL, 0)) { + //pointer check + printf("%s\n",mysql_error(&lmysql_handle)); + exit(1); + }else { + printf ("Connect Success! (Login Server)"); } - wis_db = numdb_init(); inter_guild_sql_init(); inter_storage_sql_init(); inter_party_sql_init(); - + inter_pet_sql_init(); inter_accreg_sql_init(); + atexit(inter_final); + //printf ("interserver timer initializing : %d sec...\n",autosave_interval); //i=add_timer_interval(gettick()+autosave_interval,inter_save_timer,0,0,autosave_interval); return 0; } +// finalize +int wis_db_final (void *k, void *data, va_list ap) { + struct WisData *p = (struct WisData *) data; + if (p) aFree(p); + return 0; +} +void inter_final() { + numdb_final(wis_db, wis_db_final); + + inter_guild_sql_final(); + inter_storage_sql_final(); + inter_party_sql_final(); + inter_pet_sql_final(); + + if (accreg_pt) aFree(accreg_pt); + return; +} + int inter_mapif_init(int fd) { inter_guild_mapif_init(fd); @@ -293,13 +326,13 @@ int inter_mapif_init(int fd) { //-------------------------------------------------------- // GM message sending -int mapif_GMmessage(unsigned char *mes, int len) { +int mapif_GMmessage(unsigned char *mes, int len, int sfd) { unsigned char buf[len]; WBUFW(buf, 0) = 0x3800; WBUFW(buf, 2) = len; memcpy(WBUFP(buf, 4), mes, len-4); - mapif_sendall(buf, len); + mapif_sendallwos(sfd, buf, len); printf("\033[1;34m inter server: GM[len:%d] - '%s' \033[0m\n", len, mes); return 0; } @@ -322,7 +355,7 @@ int mapif_wis_message(struct WisData *wd) { int mapif_wis_end(struct WisData *wd,int flag) { unsigned char buf[27]; - + WBUFW(buf, 0)=0x3802; memcpy(WBUFP(buf, 2),wd->src,24); WBUFB(buf,26)=flag; @@ -345,7 +378,7 @@ int mapif_account_reg_reply(int fd,int account_id) { struct accreg *reg=accreg_pt; inter_accreg_fromsql(account_id,reg); - + WFIFOW(fd,0)=0x3804; WFIFOL(fd,4)=account_id; if(reg->reg_num==0){ @@ -362,6 +395,27 @@ int mapif_account_reg_reply(int fd,int account_id) return 0; } +int mapif_send_gmaccounts() +{ + int i, len = 4; + unsigned char buf[32000]; + + // forward the gm accounts to the map server + len = 4; + WBUFW(buf,0) = 0x2b15; + + for(i = 0; i < GM_num; i++) { + WBUFL(buf, len) = gm_account[i].account_id; + WBUFB(buf, len+4) = (unsigned char)gm_account[i].level; + len += 5; + } + WBUFW(buf, 2) = len; + mapif_sendall(buf, len); + + return 0; +} + + //-------------------------------------------------------- // Existence check of WISP data @@ -384,12 +438,12 @@ int check_ttl_wisdata() { wis_delnum = 0; numdb_foreach(wis_db, check_ttl_wisdata_sub, tick); for(i = 0; i < wis_delnum; i++) { - struct WisData *wd = numdb_search(wis_db, wis_dellist[i]); + struct WisData *wd = (struct WisData*)numdb_search(wis_db, wis_dellist[i]); printf("inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst); // removed. not send information after a timeout. Just no answer for the player //mapif_wis_end(wd, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target numdb_erase(wis_db, wd->id); - free(wd); + aFree(wd); } } while(wis_delnum >= WISDELLIST_MAX); @@ -401,7 +455,7 @@ int check_ttl_wisdata() { // GM message sending int mapif_parse_GMmessage(int fd) { - mapif_GMmessage(RFIFOP(fd, 4), RFIFOW(fd, 2)); + mapif_GMmessage(RFIFOP(fd, 4), RFIFOW(fd, 2), fd); return 0; } @@ -410,6 +464,7 @@ int mapif_parse_GMmessage(int fd) int mapif_parse_WisRequest(int fd) { struct WisData* wd; static int wisid = 0; + char t_name[32]; if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) { printf("inter: Wis message size too long.\n"); @@ -418,7 +473,8 @@ int mapif_parse_WisRequest(int fd) { printf("inter: Wis message doesn't exist.\n"); return 0; } - sprintf (tmp_sql, "SELECT `name` FROM `%s` WHERE `char_id`='%d'",char_db, (int) RFIFOP(fd,28)); + sprintf (tmp_sql, "SELECT `name` FROM `%s` WHERE `name`='%s'", + char_db, jstrescapecpy(t_name, (char *)RFIFOP(fd,28))); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); } @@ -435,9 +491,9 @@ int mapif_parse_WisRequest(int fd) { } else { // to be sure of the correct name, rewrite it memset(RFIFOP(fd,28), 0, 24); - strncpy(RFIFOP(fd,28), sql_row[0], 24); + strncpy((char*)RFIFOP(fd,28), sql_row[0], 24); // if source is destination, don't ask other servers. - if (strcmp(RFIFOP(fd,4),RFIFOP(fd,28)) == 0) { + if (strcmp((char*)RFIFOP(fd,4),(char*)RFIFOP(fd,28)) == 0) { unsigned char buf[27]; WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), 24); @@ -461,7 +517,12 @@ int mapif_parse_WisRequest(int fd) { mapif_wis_message(wd); } } - + + //Freeing ... O.o + if(sql_res){ + mysql_free_result(sql_res); + } + return 0; } @@ -469,7 +530,7 @@ int mapif_parse_WisRequest(int fd) { // Wisp/page transmission result int mapif_parse_WisReply(int fd) { int id = RFIFOL(fd,2), flag = RFIFOB(fd,6); - struct WisData *wd = numdb_search(wis_db, id); + struct WisData *wd = (struct WisData*)numdb_search(wis_db, id); if (wd == NULL) return 0; // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server @@ -477,7 +538,7 @@ int mapif_parse_WisReply(int fd) { if ((--wd->count) <= 0 || flag != 1) { mapif_wis_end(wd, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target numdb_erase(wis_db, id); - free(wd); + aFree(wd); } return 0; @@ -491,13 +552,13 @@ int mapif_parse_AccReg(int fd) struct accreg *reg=accreg_pt; int account_id = RFIFOL(fd,4); memset(accreg_pt,0,sizeof(struct accreg)); - + for(j=0,p=8;j<ACCOUNT_REG_NUM && p<RFIFOW(fd,2);j++,p+=36){ memcpy(reg->reg[j].str,RFIFOP(fd,p),32); reg->reg[j].value=RFIFOL(fd,p+32); } reg->reg_num=j; - + inter_accreg_tosql(account_id,reg); mapif_account_reg(fd,RFIFOP(fd,0)); // Send confirm message to map return 0; @@ -526,7 +587,7 @@ int inter_parse_frommap(int fd) // ƒpƒPƒbƒg’·‚𒲂ׂé if( (len=inter_check_length(fd,inter_recv_packet_length[cmd-0x3000]))==0 ) return 2; - + switch(cmd){ case 0x3000: mapif_parse_GMmessage(fd); break; case 0x3001: mapif_parse_WisRequest(fd); break; @@ -556,9 +617,9 @@ int inter_check_length(int fd, int length) return 0; length = RFIFOW(fd, 2); } - + if(RFIFOREST(fd)<length) // packet not yet return 0; - + return length; } diff --git a/src/char_sql/inter.h b/src/char_sql/inter.h index 398088504..9265a8d82 100644 --- a/src/char_sql/inter.h +++ b/src/char_sql/inter.h @@ -2,9 +2,10 @@ #define _INTER_H_ int inter_init(const char *file); +void inter_final(); int inter_parse_frommap(int fd); int inter_mapif_init(int fd); - +int mapif_send_gmaccounts(); int inter_check_length(int fd,int length); @@ -24,6 +25,11 @@ extern MYSQL_RES* sql_res ; extern MYSQL_ROW sql_row ; extern int sql_cnt; +extern MYSQL lmysql_handle; +extern char tmp_lsql[65535]; +extern MYSQL_RES* lsql_res ; +extern MYSQL_ROW lsql_row ; + extern int char_server_port; extern char char_server_ip[32]; extern char char_server_id[32]; diff --git a/src/char_sql/itemdb.c b/src/char_sql/itemdb.c index d045189a0..bc3e8603e 100644 --- a/src/char_sql/itemdb.c +++ b/src/char_sql/itemdb.c @@ -13,8 +13,6 @@ #include "memwatch.h" #endif -#define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y) - #define MAX_RANDITEM 2000 // ** ITEMDB_OVERRIDE_NAME_VERBOSE ** @@ -33,7 +31,7 @@ struct item_data* itemdb_search(int nameid) { struct item_data *id; - id=numdb_search(item_db,nameid); + id = (struct item_data*)numdb_search(item_db,nameid); if(id) return id; CREATE(id, struct item_data, 1); @@ -123,7 +121,7 @@ static int itemdb_readdb(void) } if(str[0]==NULL) continue; - + nameid=atoi(str[0]); if(nameid<=0 || nameid>=20000) continue; @@ -174,7 +172,7 @@ static int itemdb_read_sqldb(void) // sql item_db read, shortened version of map // Insert a new row into the item database /* - id = calloc(sizeof(struct item_data), 1); + id = aCalloc(sizeof(struct item_data), 1); if (id == NULL) { printf("out of memory : itemdb_read_sqldb\n"); @@ -187,7 +185,7 @@ static int itemdb_read_sqldb(void) // sql item_db read, shortened version of map // ---------- */ id=itemdb_search(nameid); - + memcpy(id->name, sql_row[1], 24); memcpy(id->jname, sql_row[2], 24); @@ -214,12 +212,12 @@ static int itemdb_final(void *key,void *data,va_list ap) { struct item_data *id; - id=data; + id = (struct item_data*)data; if(id->use_script) - free(id->use_script); + aFree(id->use_script); if(id->equip_script) - free(id->equip_script); - free(id); + aFree(id->equip_script); + aFree(id); return 0; } diff --git a/src/char_sql/itemdb.h b/src/char_sql/itemdb.h index dea835e78..762873c8e 100644 --- a/src/char_sql/itemdb.h +++ b/src/char_sql/itemdb.h @@ -6,7 +6,7 @@ struct item_data { char name[24],jname[24]; int value_buy,value_sell,value_notdc,value_notoc; int type; - int class; + int class_; int sex; int equip; int weight; diff --git a/src/char_sql/make.sh b/src/char_sql/make.sh index a4ca8b5e4..6ee175f73 100644 --- a/src/char_sql/make.sh +++ b/src/char_sql/make.sh @@ -6,6 +6,5 @@ gcc -c int_pet.c -I/usr/local/include/mysql/ gcc -c int_storage.c -I/usr/local/include/mysql/ gcc -c inter.c -I/usr/local/include/mysql/ - gcc -c strlib.c gcc -c itemdb.c -I../common/ - gcc -o ../char-server inter.o char.o int_pet.o int_storage.o int_guild.o int_party.o strlib.o itemdb.o ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o -L/usr/local/lib/mysql -lmysqlclient -lz + gcc -o ../char-server inter.o char.o int_pet.o int_storage.o int_guild.o int_party.o ../common/strlib.o itemdb.o ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o -L/usr/local/lib/mysql -lmysqlclient -lz diff --git a/src/char_sql/strlib.h b/src/char_sql/strlib.h deleted file mode 100644 index 6b6169083..000000000 --- a/src/char_sql/strlib.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _J_STR_LIB_H_ -#define _J_STR_LIB_H_ -#define J_MAX_MALLOC_SIZE 65535 -// String function library. -// code by Jioh L. Jung (ziozzang@4wish.net) -// This code is under license "BSD" -unsigned char* jstrescape (unsigned char* pt); -unsigned char* jstrescapecpy (unsigned char* pt,unsigned char* spt); -int jmemescapecpy (unsigned char* pt,unsigned char* spt, int size); -#endif diff --git a/src/common/GNUmakefile b/src/common/GNUmakefile deleted file mode 100644 index b15d4d481..000000000 --- a/src/common/GNUmakefile +++ /dev/null @@ -1,14 +0,0 @@ -txt sql all: core.o socket.o timer.o grfio.o db.o lock.o nullpo.o malloc.o showmsg.o - -core.o: core.c core.h showmsg.h -socket.o: socket.c socket.h mmo.h showmsg.h -timer.o: timer.c timer.h showmsg.h -grfio.o: grfio.c grfio.h showmsg.h -db.o: db.c db.h showmsg.h -lock.o: lock.h showmsg.h -nullpo.o: nullpo.c nullpo.h showmsg.h -malloc.o: malloc.c malloc.h showmsg.h -showmsg.o: showmsg.c showmsg.h - -clean: - rm -f *.o diff --git a/src/common/Makefile b/src/common/Makefile index b15d4d481..7a00c5a3c 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -1,14 +1,23 @@ -txt sql all: core.o socket.o timer.o grfio.o db.o lock.o nullpo.o malloc.o showmsg.o - -core.o: core.c core.h showmsg.h -socket.o: socket.c socket.h mmo.h showmsg.h -timer.o: timer.c timer.h showmsg.h -grfio.o: grfio.c grfio.h showmsg.h -db.o: db.c db.h showmsg.h -lock.o: lock.h showmsg.h -nullpo.o: nullpo.c nullpo.h showmsg.h -malloc.o: malloc.c malloc.h showmsg.h -showmsg.o: showmsg.c showmsg.h +txt sql all: obj common + +obj: + mkdir obj + +common: obj/core.o obj/socket.o obj/timer.o obj/grfio.o obj/db.o obj/lock.o obj/nullpo.o obj/malloc.o obj/showmsg.o obj/strlib.o obj/utils.o + +obj/%.o: %.c + $(COMPILE.c) $(OUTPUT_OPTION) $< + +obj/core.o: core.c core.h showmsg.h +obj/socket.o: socket.c socket.h mmo.h showmsg.h dll.h +obj/timer.o: timer.c timer.h showmsg.h +obj/grfio.o: grfio.c grfio.h showmsg.h +obj/db.o: db.c db.h showmsg.h +obj/lock.o: lock.h showmsg.h +obj/nullpo.o: nullpo.c nullpo.h showmsg.h +obj/malloc.o: malloc.c malloc.h showmsg.h +obj/showmsg.o: showmsg.c showmsg.h +obj/strlib.o: strlib.c strlib.h utils.h clean: - rm -f *.o + rm -rf *.o obj diff --git a/src/common/buffer.h b/src/common/buffer.h new file mode 100644 index 000000000..ea94380ce --- /dev/null +++ b/src/common/buffer.h @@ -0,0 +1,18 @@ +#ifndef _BUFFER_H_ +#define _BUFFER_H_ + +// Full credit for this goes to Shinomori [Ajarn] + +#ifdef __GNUC__ // GCC has variable length arrays + +#define CREATE_BUFFER(name, type, size) type name[size] +#define DELETE_BUFFER(name) + +#else // others don't, so we emulate them + +#define CREATE_BUFFER(name, type, size) type *name=(type*)aCalloc(size,sizeof(type)) +#define DELETE_BUFFER(name) aFree(name);name=NULL + +#endif + +#endif diff --git a/src/common/core.c b/src/common/core.c index 167b38efb..0a9e76120 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -8,17 +8,29 @@ #endif #include <signal.h> #include <string.h> +#ifdef DUMPSTACK + #ifndef CYGWIN // HAVE_EXECINFO_H + #include <execinfo.h> + #endif +#endif #include "core.h" -#include "socket.h" -#include "timer.h" -#include "version.h" -#include "showmsg.h" +#include "../common/mmo.h" +#include "../common/malloc.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/version.h" +#include "../common/showmsg.h" #ifdef MEMWATCH #include "memwatch.h" #endif +char *argp; +int runflag = 1; +char SERVER_TYPE = SERVER_NONE; +unsigned long ticks = 0; // by MC Cameri +char pid_file[256]; static void (*term_func)(void)=NULL; /*====================================== @@ -30,14 +42,54 @@ void set_termfunc(void (*termfunc)(void)) term_func = termfunc; } +// Added by Gabuzomeu +// +// This is an implementation of signal() using sigaction() for portability. +// (sigaction() is POSIX; signal() is not.) Taken from Stevens' _Advanced +// Programming in the UNIX Environment_. +// +#ifndef SIGPIPE +#define SIGPIPE SIGINT +#endif + +#ifndef POSIX +#define compat_signal(signo, func) signal(signo, func) +#else +sigfunc *compat_signal(int signo, sigfunc *func) +{ + struct sigaction sact, oact; + + sact.sa_handler = func; + sigemptyset(&sact.sa_mask); + sact.sa_flags = 0; +#ifdef SA_INTERRUPT + sact.sa_flags |= SA_INTERRUPT; /* SunOS */ +#endif + + if (sigaction(signo, &sact, &oact) < 0) + return (SIG_ERR); + + return (oact.sa_handler); +} +#endif + /*====================================== * CORE : Signal Sub Function *-------------------------------------- */ - +// for handling certain signals ourselves, like SIGPIPE +static void sig_ignore(int sn) { + printf ("Broken pipe found... closing socket\n"); // set to eof in socket.c + return; // does nothing here +} static void sig_proc(int sn) { int i; + static int is_called = 0; + + if(is_called++) + return; + switch(sn){ case SIGINT: case SIGTERM: @@ -53,6 +105,66 @@ static void sig_proc(int sn) } } +/*========================================= + * Dumps the stack using glibc's backtrace + *----------------------------------------- + */ +#ifndef DUMPSTACK + #define sig_dump SIG_DFL +#else + #ifdef CYGWIN + #define FOPEN_ freopen + extern void cygwin_stackdump(); + #else + #define FOPEN_(fn,m,s) fopen(fn,m) + #endif +extern const char *strsignal(int); +void sig_dump(int sn) +{ + FILE *fp; + char file[256]; + int no = 0; + + #ifndef CYGWIN + void* array[20]; + char **stack; + size_t size; + #endif + + // search for a usable filename + do { + sprintf (file, "log/%s%04d.stackdump", argp, ++no); + } while((fp = fopen(file,"r")) && (fclose(fp), no < 9999)); + // dump the trace into the file + + if ((fp = FOPEN_(file, "w", stderr)) != NULL) { + printf ("Dumping stack... "); + fprintf(fp, "Exception: %s \n", strsignal(sn)); + fflush (fp); + + #ifdef CYGWIN + cygwin_stackdump (); + #else + fprintf(fp, "Stack trace:\n"); + size = backtrace (array, 20); + stack = backtrace_symbols (array, size); + for (no = 0; no < size; no++) { + fprintf(fp, "%s\n", stack[no]); + } + fprintf(fp,"End of stack trace\n"); + aFree(stack); + #endif + + printf ("Done.\n"); + fflush(stdout); + fclose(fp); + } + // Pass the signal to the system's default handler + compat_signal(sn, SIG_DFL); + raise(sn); +} +#endif + int get_svn_revision(char *svnentry) { // Warning: minor syntax checking char line[1024]; int rev = 0; @@ -60,12 +172,13 @@ int get_svn_revision(char *svnentry) { // Warning: minor syntax checking if ((fp = fopen(svnentry, "r")) == NULL) { return 0; } else { - while (fgets(line,1023,fp)) if (strstr(line,"revision=")) break; + while (fgets(line,1023,fp)) + if (strstr(line,"revision=")) break; fclose(fp); - if (sscanf(line," %*[^\"]\"%d%*[^\n]",&rev)==1) - return rev; + if (sscanf(line," %*[^\"]\"%d%*[^\n]",&rev) == 1) + return rev; else - return 0; + return 0; } // return 0; } @@ -87,7 +200,7 @@ static void display_title(void) // \033[1m : use bold for font printf("\033[2J"); // clear screen and go up/left (0, 0 position in text) printf("\033[37;44m (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)\033[K\033[0m\n"); // white writing (37) on blue background (44), \033[K clean until end of file - printf("\033[0;44m (\033[1;33m (c)2004 eAthena Development Team presents \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) + printf("\033[0;44m (\033[1;33m (c)2005 eAthena Development Team presents \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) printf("\033[0;44m (\033[1m ______ __ __ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char printf("\033[0;44m (\033[1m /\\ _ \\/\\ \\__/\\ \\ v%2d.%02d.%02d \033[0;44m)\033[K\033[0m\n", ATHENA_MAJOR_VERSION, ATHENA_MINOR_VERSION, ATHENA_REVISION); // 1: bold char, 0: normal char printf("\033[0;44m (\033[1m __\\ \\ \\_\\ \\ \\ ,_\\ \\ \\___ __ ___ __ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char @@ -100,80 +213,115 @@ static void display_title(void) printf("\033[0;44m (\033[1m ( e | n | g | l | i | s | h ) ( A | t | h | e | n | a ) \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char printf("\033[0;44m (\033[1m \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char printf("\033[0;44m (\033[1m \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) - printf("\033[0;44m (\033[1;33m Advanced Fusion Maps (c) 2003-2004 The Fusion Project \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) + printf("\033[0;44m (\033[1;33m Advanced Fusion Maps (c) 2003-2005 The Fusion Project \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) printf("\033[37;44m (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)\033[K\033[0m\n\n"); // reset color if ((revision = get_svn_revision(".svn\\entries"))>0) { - snprintf(tmp_output,sizeof(tmp_output),"SVN Revision: %d.\n",revision); + snprintf(tmp_output,sizeof(tmp_output),"SVN Revision: '"CL_WHITE"%d"CL_RESET"'.\n",revision); ShowInfo(tmp_output); } } -// Added by Gabuzomeu -// -// This is an implementation of signal() using sigaction() for portability. -// (sigaction() is POSIX; signal() is not.) Taken from Stevens' _Advanced -// Programming in the UNIX Environment_. -// -#ifndef SIGPIPE -#define SIGPIPE SIGINT -#endif +/*====================================== + * CORE : MAINROUTINE + *-------------------------------------- + */ -#ifndef POSIX -#define compat_signal(signo, func) signal(signo, func) -#else -sigfunc *compat_signal(int signo, sigfunc *func) -{ - struct sigaction sact, oact; +void pid_delete(void) { + unlink(pid_file); +} - sact.sa_handler = func; - sigemptyset(&sact.sa_mask); - sact.sa_flags = 0; -#ifdef SA_INTERRUPT - sact.sa_flags |= SA_INTERRUPT; /* SunOS */ +void pid_create(const char* file) { + FILE *fp; + int len = strlen(file); + strcpy(pid_file,file); + if(len > 4 && pid_file[len - 4] == '.') { + pid_file[len - 4] = 0; + } + strcat(pid_file,".pid"); + fp = fopen(pid_file,"w"); + if(fp) { +#ifdef _WIN32 + fprintf(fp,"%d",GetCurrentProcessId()); +#else + fprintf(fp,"%d",getpid()); #endif + fclose(fp); + atexit(pid_delete); + } +} - if (sigaction(signo, &sact, &oact) < 0) - return (SIG_ERR); +#define LOG_UPTIME 0 +void log_uptime(void) +{ +#if LOG_UPTIME + time_t curtime; + char curtime2[24]; + FILE *fp; + long seconds = 0, day = 24*60*60, hour = 60*60, + minute = 60, days = 0, hours = 0, minutes = 0; - return (oact.sa_handler); -} -#endif + fp = fopen("log/uptime.log","a"); + if (fp) { + time(&curtime); + strftime(curtime2, 24, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + seconds = (gettick()-ticks)/CLOCKS_PER_SEC; + days = seconds/day; + seconds -= (seconds/day>0)?(seconds/day)*day:0; + hours = seconds/hour; + seconds -= (seconds/hour>0)?(seconds/hour)*hour:0; + minutes = seconds/minute; + seconds -= (seconds/minute>0)?(seconds/minute)*minute:0; -/*====================================== - * CORE : MAINROUTINE - *-------------------------------------- - */ + fprintf(fp, "%s: %s uptime - %ld days, %ld hours, %ld minutes, %ld seconds.\n", + curtime2, argp, days, hours, minutes, seconds); + fclose(fp); + } -int runflag = 1; + return; +#endif +} int main(int argc,char **argv) { int next; + if ((argp = strstr(argv[0], "./")) != NULL) + argp+=2; + else argp = argv[0]; + + display_title(); + + do_init_memmgr(argp); // ˆê”Ôʼn‚ÉŽÀs‚·‚é•K—v‚ª‚ ‚é + atexit(log_uptime); + pid_create(argp); Net_Init(); do_socket(); - compat_signal(SIGPIPE,SIG_IGN); + compat_signal(SIGPIPE, sig_ignore); compat_signal(SIGTERM,sig_proc); compat_signal(SIGINT,sig_proc); - + // Signal to create coredumps by system when necessary (crash) - compat_signal(SIGSEGV, SIG_DFL); -#ifndef _WIN32 - compat_signal(SIGBUS, SIG_DFL); - compat_signal(SIGTRAP, SIG_DFL); -#endif - compat_signal(SIGILL, SIG_DFL); + compat_signal(SIGSEGV, sig_dump); + compat_signal(SIGFPE, sig_dump); + compat_signal(SIGILL, sig_dump); + #ifndef _WIN32 + compat_signal(SIGBUS, sig_dump); + compat_signal(SIGTRAP, SIG_DFL); + #endif - display_title(); + tick_ = time(0); + ticks = gettick(); do_init(argc,argv); + while(runflag){ next=do_timer(gettick_nocache()); do_sendrecv(next); do_parsepacket(); } + return 0; } diff --git a/src/common/core.h b/src/common/core.h index bc2be02c2..e9b5c8227 100644 --- a/src/common/core.h +++ b/src/common/core.h @@ -3,10 +3,19 @@ #ifndef _CORE_H_ #define _CORE_H_ +extern char *argp; extern int runflag; +extern unsigned long ticks; +extern char SERVER_TYPE; -int do_init(int,char**); +enum { + SERVER_NONE, + SERVER_LOGIN, + SERVER_CHAR, + SERVER_MAP, +}; +int do_init(int,char**); void set_termfunc(void (*termfunc)(void)); #endif // _CORE_H_ diff --git a/src/common/db.c b/src/common/db.c index 58f0ea4f7..377128e8f 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -1,18 +1,26 @@ // $Id: db.c,v 1.2 2004/09/23 14:43:06 MouseJstr Exp $ -// #define MALLOC_DBN #include <stdio.h> #include <stdlib.h> #include <string.h> #include "db.h" #include "mmo.h" #include "utils.h" +#include "malloc.h" #ifdef MEMWATCH #include "memwatch.h" #endif -#define ROOT_SIZE 4096 +//#define MALLOC_DBN + +// Backup cleaning routine in case the core doesn't do so properly, +// only enabled if malloc_dbn is not defined. +// As a temporary solution the root of the problem should still be found and fixed +struct dbn *head; +struct dbn *tail; + #ifdef MALLOC_DBN +#define ROOT_SIZE 4096 static struct dbn *dbn_root[512], *dbn_free; static int dbn_root_rest=0,dbn_root_num=0; @@ -39,20 +47,50 @@ static void free_dbn(struct dbn* add_dbn) add_dbn->parent = dbn_free; dbn_free = add_dbn; } + +void exit_dbn(void) +{ + int i; + + for (i=0;i<dbn_root_num;i++) + if (dbn_root[i]) + aFree(dbn_root[i]); + + dbn_root_rest=0; + dbn_root_num=0; + + return; +} +#else +void exit_dbn(void) +{ + int i = 0; + struct dbn *p = head, *p2; + while (p) { + p2 = p->next; + aFree(p); + p = p2; + i++; + } + //printf ("freed %d stray dbn\n", i); + return; +} #endif +// maybe change the void* to const char* ??? static int strdb_cmp(struct dbt* table,void* a,void* b) { if(table->maxlen) - return strncmp(a,b,table->maxlen); - return strcmp(a,b); + return strncmp((const char*)a,(const char*)b,table->maxlen); + return strcmp((const char*)a,(const char*)b); } +// maybe change the void* to unsigned char* ??? static unsigned int strdb_hash(struct dbt* table,void* a) { int i; unsigned int h; - unsigned char *p=a; + unsigned char *p = (unsigned char*)a; i=table->maxlen; if(i==0) i=0x7fffffff; @@ -62,7 +100,7 @@ static unsigned int strdb_hash(struct dbt* table,void* a) return h; } -struct dbt* strdb_init(int maxlen) +struct dbt* strdb_init_(int maxlen,const char *file,int line) { int i; struct dbt* table; @@ -74,6 +112,9 @@ struct dbt* strdb_init(int maxlen) table->maxlen=maxlen; for(i=0;i<HASH_SIZE;i++) table->ht[i]=NULL; + table->alloc_file = file; + table->alloc_line = line; + table->item_count = 0; return table; } @@ -95,7 +136,7 @@ static unsigned int numdb_hash(struct dbt* table,void* a) return (unsigned int)a; } -struct dbt* numdb_init(void) +struct dbt* numdb_init_(const char *file,int line) { int i; struct dbt* table; @@ -107,6 +148,9 @@ struct dbt* numdb_init(void) table->maxlen=sizeof(int); for(i=0;i<HASH_SIZE;i++) table->ht[i]=NULL; + table->alloc_file = file; + table->alloc_line = line; + table->item_count = 0; return table; } @@ -130,14 +174,14 @@ void * db_search2(struct dbt *table, const char *key) { int i,sp; struct dbn *p,*pn,*stack[64]; - int slen = strlen(key); + int slen = strlen(key); for(i=0;i<HASH_SIZE;i++){ if((p=table->ht[i])==NULL) continue; sp=0; while(1){ - if (strnicmp(key, p->key, slen) == 0) + if (strnicmp(key, (const char*)p->key, slen) == 0) return p->data; if((pn=p->left)!=NULL){ if(p->right){ @@ -345,6 +389,29 @@ static void db_rebalance_erase(struct dbn *z,struct dbn **root) } } +void db_free_lock(struct dbt *table) { + table->free_lock++; +} + +void db_free_unlock(struct dbt *table) { + if(--table->free_lock == 0) { + int i; + for(i = 0; i < table->free_count ; i++) { + db_rebalance_erase(table->free_list[i].z,table->free_list[i].root); + if(table->cmp == strdb_cmp) { + aFree(table->free_list[i].z->key); + } +#ifdef MALLOC_DBN + free_dbn(table->free_list[i].z); +#else + aFree(table->free_list[i].z); +#endif + table->item_count--; + } + table->free_count = 0; + } +} + struct dbn* db_insert(struct dbt *table,void* key,void* data) { struct dbn *p,*priv; @@ -354,10 +421,33 @@ struct dbn* db_insert(struct dbt *table,void* key,void* data) for(c=0,priv=NULL ,p = table->ht[hash];p;){ c=table->cmp(table,key,p->key); if(c==0){ // replace - if (table->release) - table->release(p, 3); + if (table->release) + table->release(p, 3); + if(p->deleted) { + // 휂³‚ꂽƒf[ƒ^‚Ȃ̂ÅAfree_list ã‚Ì휗\’è‚ðÁ‚· + int i; + for(i = 0; i < table->free_count ; i++) { + if(table->free_list[i].z == p) { + memmove( + &table->free_list[i], + &table->free_list[i+1], + sizeof(struct db_free)*(table->free_count - i - 1) + ); + break; + } + } + if(i == table->free_count || table->free_count <= 0) { + printf("db_insert: cannnot find deleted db node.\n"); + } else { + table->free_count--; + if(table->cmp == strdb_cmp) { + aFree(p->key); + } + } + } p->data=data; p->key=key; + p->deleted = 0; return p; } priv=p; @@ -382,6 +472,17 @@ struct dbn* db_insert(struct dbt *table,void* key,void* data) p->key = key; p->data = data; p->color = RED; + p->deleted = 0; + p->prev = NULL; + p->next = NULL; + if (head == NULL) + head = tail = p; + else { + p->prev = tail; + tail->next = p; + tail = p; + } + if(c==0){ // hash entry is empty table->ht[hash] = p; p->color = BLACK; @@ -397,6 +498,8 @@ struct dbn* db_insert(struct dbt *table,void* key,void* data) db_rebalance(p,&table->ht[hash]); } } + table->item_count++; + return p; } @@ -419,29 +522,69 @@ void* db_erase(struct dbt *table,void* key) if(!p) return NULL; data=p->data; - db_rebalance_erase(p,&table->ht[hash]); -#ifdef MALLOC_DBN - free_dbn(p); -#else - free(p); -#endif + if(table->free_lock) { + if(table->free_count == table->free_max) { + table->free_max += 32; + table->free_list = (struct db_free*)realloc(table->free_list,sizeof(struct db_free) * table->free_max); + } + table->free_list[table->free_count].z = p; + table->free_list[table->free_count].root = &table->ht[hash]; + table->free_count++; + p->deleted = 1; + p->data = NULL; + if(table->cmp == strdb_cmp) { + if(table->maxlen) { + char *key = (char*)malloc(table->maxlen); + memcpy(key,p->key,table->maxlen); + p->key = key; + } else { + p->key = strdup((const char*)p->key); + } + } + } else { + db_rebalance_erase(p,&table->ht[hash]); + if (p->prev) + p->prev->next = p->next; + else + head = p->next; + if (p->next) + p->next->prev = p->prev; + else + tail = p->prev; + + #ifdef MALLOC_DBN + free_dbn(p); + #else + aFree(p); + #endif + table->item_count--; + } return data; } void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) { int i,sp; + int count = table->item_count; // red-black tree‚Ȃ̂Å64ŒÂstack‚ª‚ ‚ê‚Î2^32ŒÂƒm[ƒh‚܂őåä•v struct dbn *p,*pn,*stack[64]; va_list ap; va_start(ap,func); + db_free_lock(table); for(i=0;i<HASH_SIZE;i++){ if((p=table->ht[i])==NULL) continue; sp=0; while(1){ - func(p->key,p->data,ap); + //reverted it back. sorry that brought thios bug from Freya [Lupus] + //if (!p->data) { + // printf("Warning: no data for key %d in db_foreach (db.c) !\n",(int)p->key); + //} else { + if(!p->deleted) + func(p->key, p->data, ap); + count--; + //} if((pn=p->left)!=NULL){ if(p->right){ stack[sp++]=p->right; @@ -458,6 +601,13 @@ void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) } } } + db_free_unlock(table); + if(count) { + printf( + "db_foreach : data lost %d item(s) allocated from %s line %d\n", + count,table->alloc_file,table->alloc_line + ); + } va_end(ap); } @@ -468,12 +618,13 @@ void db_final(struct dbt *table,int (*func)(void*,void*,va_list),...) va_list ap; va_start(ap,func); + db_free_lock(table); for(i=0;i<HASH_SIZE;i++){ if((p=table->ht[i])==NULL) continue; sp=0; while(1){ - if(func) + if(func && !p->deleted) func(p->key,p->data,ap); if((pn=p->left)!=NULL){ if(p->right){ @@ -488,14 +639,24 @@ void db_final(struct dbt *table,int (*func)(void*,void*,va_list),...) pn=stack[--sp]; } } + if (p->prev) + p->prev->next = p->next; + else + head = p->next; + if (p->next) + p->next->prev = p->prev; + else + tail = p->prev; #ifdef MALLOC_DBN free_dbn(p); #else - free(p); + aFree(p); #endif p=pn; } } - free(table); + db_free_unlock(table); + aFree(table->free_list); + aFree(table); va_end(ap); } diff --git a/src/common/db.h b/src/common/db.h index ea9aceab0..6980099cf 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -13,6 +13,14 @@ struct dbn { int color; void *key; void *data; + int deleted; // íœÏ‚݃tƒ‰ƒO(db_foreach) + struct dbn *next; + struct dbn *prev; +}; + +struct db_free { + struct dbn *z; + struct dbn **root; }; struct dbt { @@ -22,6 +30,15 @@ struct dbt { void (*release)(struct dbn*,int which); int maxlen; struct dbn *ht[HASH_SIZE]; + int item_count; // vf? + const char* alloc_file; // DB?t@C + int alloc_line; // DB?s + // db_foreach “à•”‚Ådb_erase ‚³‚ê‚é‘Îô‚Æ‚µ‚ÄA + // db_foreach ‚ªI‚í‚é‚܂ŃƒbƒN‚·‚邱‚Ƃɂ·‚é + struct db_free *free_list; + int free_count; + int free_max; + int free_lock; }; #define strdb_search(t,k) db_search((t),(void*)(k)) @@ -34,14 +51,18 @@ struct dbt { #define numdb_erase(t,k) db_erase ((t),(void*)(k)) #define numdb_foreach db_foreach #define numdb_final db_final +#define strdb_init(a) strdb_init_(a,__FILE__,__LINE__) +#define numdb_init() numdb_init_(__FILE__,__LINE__) + +struct dbt* strdb_init_(int maxlen,const char *file,int line); +struct dbt* numdb_init_(const char *file,int line); -struct dbt* strdb_init(int maxlen); -struct dbt* numdb_init(void); void* db_search(struct dbt *table,void* key); void* db_search2(struct dbt *table, const char *key); // [MouseJstr] struct dbn* db_insert(struct dbt *table,void* key,void* data); void* db_erase(struct dbt *table,void* key); void db_foreach(struct dbt*,int(*)(void*,void*,va_list),...); void db_final(struct dbt*,int(*)(void*,void*,va_list),...); +void exit_dbn(void); #endif diff --git a/src/common/dll.h b/src/common/dll.h new file mode 100644 index 000000000..50854da4d --- /dev/null +++ b/src/common/dll.h @@ -0,0 +1,25 @@ +
+#ifndef _DLL_H_
+#define _DLL_H_
+
+#ifdef _WIN32
+
+ #include <windows.h>
+ #define DLL_OPEN(x) LoadLibrary(x)
+ #define DLL_SYM(x,y,z) (FARPROC)(x) = GetProcAddress(y,z)
+ #define DLL_CLOSE(x) FreeLibrary(x)
+ #define DLL HINSTANCE
+
+#else
+
+ #include <dlfcn.h>
+ #define DLL_OPEN(x) dlopen(x,RTLD_NOW)
+ #define DLL_SYM(x,y,z) (x) = (void *)dlsym(y,z)
+ #define DLL_CLOSE(x) dlclose(x)
+ #define DLL void *
+
+#endif
+
+#endif // _DLL_H_
+
+
diff --git a/src/common/grfio.c b/src/common/grfio.c index ff01b6e76..1a3829bf7 100644 --- a/src/common/grfio.c +++ b/src/common/grfio.c @@ -25,11 +25,50 @@ #include <ctype.h> #include <sys/stat.h> -#include <zlib.h> - -#include "utils.h" #include "grfio.h" -#include "mmo.h" +#include "../common/utils.h" +#include "../common/mmo.h" +#include "../common/showmsg.h" +#include "../common/malloc.h" + +#ifdef _WIN32 + #ifdef LOCALZLIB + #include "zlib.h" + #define zlib_inflateInit inflateInit + #define zlib_inflate inflate + #define zlib_inflateEnd inflateEnd + #define zlib_deflateInit deflateInit + #define zlib_deflate deflate + #define zlib_deflateEnd deflateEnd + #else + #include "../lib/zlib_win32.h" + #include "../common/dll.h" + DLL zlib_dll; + #define zlib_inflateInit(strm) zlib_inflateInit_((strm),ZLIB_VERSION, sizeof(z_stream)) + #define zlib_deflateInit(strm, level) zlib_deflateInit_((strm),(level),ZLIB_VERSION,sizeof(z_stream)) + + int (WINAPI* zlib_inflateInit_) (z_streamp strm, const char *version, int stream_size); + int (WINAPI* zlib_inflate) (z_streamp strm, int flush); + int (WINAPI* zlib_inflateEnd) (z_streamp strm); + + int (WINAPI* zlib_deflateInit_) (z_streamp strm, int level, const char *version, int stream_size); + int (WINAPI* zlib_deflate) (z_streamp strm, int flush); + int (WINAPI* zlib_deflateEnd) (z_streamp strm); + #endif +#else + #ifdef LOCALZLIB + #include "zlib/zlib.h" + #else + #include <zlib.h> + #endif + + #define zlib_inflateInit inflateInit + #define zlib_inflate inflate + #define zlib_inflateEnd inflateEnd + #define zlib_deflateInit deflateInit + #define zlib_deflate deflate + #define zlib_deflateEnd deflateEnd +#endif #ifdef MEMWATCH #include "memwatch.h" @@ -72,7 +111,7 @@ typedef struct { //Since char defines *FILELIST.gentry, the maximum which can be added by grfio_add becomes by 127 pieces. #define GENTRY_LIMIT 127 -#define FILELIST_LIMIT 32768 // temporary maximum, and a theory top maximum are 2G. +#define FILELIST_LIMIT 65536 // temporary maximum, and a theory top maximum are 2G. static FILELIST *filelist; static int filelist_entrys; @@ -139,7 +178,11 @@ static unsigned char NibbleData[4][64]={ */ static unsigned int getlong(unsigned char *p) { - return *p+p[1]*256+(p[2]+p[3]*256)*65536; +// return *p+p[1]*256+(p[2]+p[3]*256)*65536; + return p[0] + | p[1] << 0x08 + | p[2] << 0x10 + | p[3] << 0x18; // Shinomori } /*========================================== @@ -157,15 +200,17 @@ static void BitConvert(BYTE *Src,char *BitSwapTable) { int lop,prm; BYTE tmp[8]; - *(DWORD*)tmp=*(DWORD*)(tmp+4)=0; +// *(DWORD*)tmp=*(DWORD*)(tmp+4)=0; + memset(tmp,0,8); for(lop=0;lop!=64;lop++) { prm = BitSwapTable[lop]-1; if (Src[(prm >> 3) & 7] & BitMaskTable[prm & 7]) { tmp[(lop >> 3) & 7] |= BitMaskTable[lop & 7]; } } - *(DWORD*)Src = *(DWORD*)tmp; - *(DWORD*)(Src+4) = *(DWORD*)(tmp+4); +// *(DWORD*)Src = *(DWORD*)tmp; +// *(DWORD*)(Src+4) = *(DWORD*)(tmp+4); + memcpy(Src,tmp,8); } static void BitConvert4(BYTE *Src) @@ -193,7 +238,11 @@ static void BitConvert4(BYTE *Src) tmp[(lop >> 3) + 4] |= BitMaskTable[lop & 7]; } } - *(DWORD*)Src ^= *(DWORD*)(tmp+4); +// *(DWORD*)Src ^= *(DWORD*)(tmp+4); + Src[0] ^= tmp[4]; + Src[1] ^= tmp[5]; + Src[2] ^= tmp[6]; + Src[3] ^= tmp[7]; } static void decode_des_etc(BYTE *buf,int len,int type,int cycle) @@ -248,7 +297,7 @@ static void decode_des_etc(BYTE *buf,int len,int type,int cycle) * Grf data decode sub : zip *------------------------------------------ */ -static int decode_zip(Bytef* dest, uLongf* destLen, const Bytef* source, uLong sourceLen) +int decode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen) { z_stream stream; int err; @@ -258,26 +307,57 @@ static int decode_zip(Bytef* dest, uLongf* destLen, const Bytef* source, uLong s /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; - stream.next_out = dest; + stream.next_out = (Bytef*) dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = zlib_inflateInit(&stream); + if (err != Z_OK) return err; + + err = zlib_inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + zlib_inflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = zlib_inflateEnd(&stream); + return err; +} + +int encode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen) { + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = (Bytef*) dest; stream.avail_out = (uInt)*destLen; if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; - err = inflateInit(&stream); + err = zlib_deflateInit(&stream,Z_DEFAULT_COMPRESSION); if (err != Z_OK) return err; - err = inflate(&stream, Z_FINISH); + err = zlib_deflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { - inflateEnd(&stream); + zlib_inflateEnd(&stream); return err == Z_OK ? Z_BUF_ERROR : err; } *destLen = stream.total_out; - err = inflateEnd(&stream); + err = zlib_deflateEnd(&stream); return err; } + /*********************************************************** *** File List Sobroutines *** ***********************************************************/ @@ -315,7 +395,7 @@ FILELIST *filelist_find(char *fname) { int hash; - for(hash=filelist_hash[filehash(fname)];hash>=0;hash=filelist[hash].next) { + for(hash=filelist_hash[filehash((unsigned char *) fname)];hash>=0;hash=filelist[hash].next) { if(strcmpi(filelist[hash].fn,fname)==0) break; } @@ -339,7 +419,7 @@ static FILELIST* filelist_add(FILELIST *entry) } if (filelist_entrys>=filelist_maxentry) { - FILELIST *new_filelist = (FILELIST*)realloc( + FILELIST *new_filelist = (FILELIST*)aRealloc( (void*)filelist, (filelist_maxentry+FILELIST_ADDS)*sizeof(FILELIST) ); if (new_filelist != NULL) { filelist = new_filelist; @@ -354,7 +434,7 @@ static FILELIST* filelist_add(FILELIST *entry) memcpy( &filelist[filelist_entrys], entry, sizeof(FILELIST) ); - hash = filehash(entry->fn); + hash = filehash((unsigned char *) entry->fn); filelist[filelist_entrys].next = filelist_hash[hash]; filelist_hash[hash] = filelist_entrys; @@ -384,7 +464,7 @@ static void filelist_adjust(void) { if (filelist!=NULL) { if (filelist_maxentry>filelist_entrys) { - FILELIST *new_filelist = (FILELIST*)realloc( + FILELIST *new_filelist = (FILELIST*)aRealloc( (void*)filelist,filelist_entrys*sizeof(FILELIST) ); if (new_filelist != NULL) { filelist = new_filelist; @@ -443,17 +523,17 @@ int grfio_size(char *fname) entry = filelist_find(fname); if (entry==NULL || entry->gentry<0) { // LocalFileCheck - char lfname[256],rname[256],*p; + char lfname[256],*rname,*p; FILELIST lentry; struct stat st; - - if(strcmp(data_dir, "") != 0) { + + if(strcmp(data_dir, "") != 0 && (rname=grfio_resnametable(fname,lfname))!=NULL) { //printf("%s\t",fname); - sprintf(rname,"%s",grfio_resnametable(fname,lfname)); + //sprintf(rname,"%s",grfio_resnametable(fname,lfname)); //printf("%s\n",rname); sprintf(lfname,"%s%s",data_dir,rname); //printf("%s\n",lfname); - } + } for(p=&lfname[0];*p!=0;p++) if (*p=='\\') *p = '/'; // * At the time of Unix @@ -485,13 +565,18 @@ void* grfio_reads(char *fname, int *size) entry = filelist_find(fname); if (entry==NULL || entry->gentry<=0) { // LocalFileCheck - char lfname[256],rname[256],*p; + char lfname[256],*rname,*p; FILELIST lentry; strncpy(lfname,fname,255); - sprintf(rname,"%s",grfio_resnametable(fname,lfname)); - sprintf(lfname,"%s%s",data_dir,rname); - //printf("%s\n",lfname); + // i hope this is the correct way =p [celest] + if ((rname=grfio_resnametable(fname,lfname))!=NULL) { + char tbuf[255]; + //sprintf(rname,"%s",grfio_resnametable(fname,lfname)); + sprintf(tbuf,"%s%s",data_dir,rname); + strcpy(lfname, tbuf); + //printf("%s\n",lfname); + } for(p=&lfname[0];*p!=0;p++) if (*p=='\\') *p = '/'; // * At the time of Unix @@ -504,7 +589,7 @@ void* grfio_reads(char *fname, int *size) lentry.declen = ftell(in); } fseek(in,0,0); // SEEK_SET - buf2 = calloc(lentry.declen+1024, 1); + buf2 = (unsigned char *)aCallocA(lentry.declen+1024, 1); if (buf2==NULL) { printf("file read memory allocate error : declen\n"); goto errret; @@ -520,13 +605,13 @@ void* grfio_reads(char *fname, int *size) } else { printf("%s not found (grfio_reads)\n", fname); //goto errret; - free(buf2); + aFree(buf2); return NULL; } } } if (entry!=NULL && entry->gentry>0) { // Archive[GRF] File Read - buf = calloc(entry->srclen_aligned+1024, 1); + buf = (unsigned char *) aCallocA(entry->srclen_aligned+1024, 1); if (buf==NULL) { printf("file read memory allocate error : srclen_aligned\n"); goto errret; @@ -536,13 +621,13 @@ void* grfio_reads(char *fname, int *size) if(in==NULL) { printf("%s not found (grfio_reads)\n",gfname); //goto errret; - free(buf); + aFree(buf); return NULL; } fseek(in,entry->srcpos,0); fread(buf,1,entry->srclen_aligned,in); fclose(in); - buf2=calloc(entry->declen+1024, 1); + buf2 = (unsigned char *)aCallocA(entry->declen+1024, 1); if (buf2==NULL) { printf("file decode memory allocate error\n"); goto errret; @@ -561,16 +646,16 @@ void* grfio_reads(char *fname, int *size) } else { memcpy(buf2,buf,entry->declen); } - free(buf); + aFree(buf); } if (size!=NULL && entry!=NULL) *size = entry->declen; return buf2; errret: - if (buf!=NULL) free(buf); - if (buf2!=NULL) free(buf2); + if (buf!=NULL) aFree(buf); + if (buf2!=NULL) aFree(buf2); if (in!=NULL) fclose(in); - exit(1); //return NULL; + return NULL; } /*========================================== @@ -586,7 +671,7 @@ void* grfio_read(char *fname) * Resource filename decode *------------------------------------------ */ -static unsigned char * decode_filename(unsigned char *buf,int len) +static char * decode_filename(unsigned char *buf,int len) { int lop; for(lop=0;lop<len;lop+=8) { @@ -595,7 +680,7 @@ static unsigned char * decode_filename(unsigned char *buf,int len) BitConvert4(&buf[lop]); BitConvert(&buf[lop],BitSwapTable2); } - return buf; + return (char*)buf; } /*========================================== @@ -608,12 +693,13 @@ static int grfio_entryread(char *gfname,int gentry) int grf_size,list_size; unsigned char grf_header[0x2e]; int lop,entry,entrys,ofs,grf_version; - unsigned char *fname; + char *fname; unsigned char *grf_filelist; fp = fopen(gfname,"rb"); if(fp==NULL) { - printf("%s not found (grfio_entryread)\n",gfname); + sprintf(tmp_output,"GRF Data File not found: '"CL_WHITE"%s"CL_RESET"'.\n",gfname); + ShowWarning(tmp_output); return 1; // 1:not found error } @@ -621,7 +707,7 @@ static int grfio_entryread(char *gfname,int gentry) grf_size = ftell(fp); fseek(fp,0,0); // SEEK_SET fread(grf_header,1,0x2e,fp); - if(strcmp(grf_header,"Master of Magic") || fseek(fp,getlong(grf_header+0x1e),1)){ // SEEK_CUR + if(strcmp((const char *) grf_header,"Master of Magic") || fseek(fp,getlong(grf_header+0x1e),1)){ // SEEK_CUR fclose(fp); printf("%s read error\n",gfname); return 2; // 2:file format error @@ -631,7 +717,7 @@ static int grfio_entryread(char *gfname,int gentry) if (grf_version==0x01) { //****** Grf version 01xx ****** list_size = grf_size-ftell(fp); - grf_filelist = calloc(list_size, 1); + grf_filelist = (unsigned char *) aCallocA(list_size, 1); if(grf_filelist==NULL){ fclose(fp); printf("out of memory : grf_filelist\n"); @@ -654,7 +740,7 @@ static int grfio_entryread(char *gfname,int gentry) fname = decode_filename(grf_filelist+ofs+6,grf_filelist[ofs]-6); if(strlen(fname)>sizeof(aentry.fn)-1){ printf("file name too long : %s\n",fname); - free(grf_filelist); + aFree(grf_filelist); exit(1); } srclen=0; @@ -679,7 +765,7 @@ static int grfio_entryread(char *gfname,int gentry) aentry.srcpos = getlong(grf_filelist+ofs2+13)+0x2e; aentry.cycle = srccount; aentry.type = type; - strncpy(aentry.fn,fname,sizeof(aentry.fn)-1); + strncpy(aentry.fn, fname,sizeof(aentry.fn)-1); #ifdef GRFIO_LOCAL aentry.gentry = -(gentry+1); // As Flag for making it a negative number carrying out the first time LocalFileCheck #else @@ -689,7 +775,7 @@ static int grfio_entryread(char *gfname,int gentry) } ofs = ofs2 + 17; } - free(grf_filelist); + aFree(grf_filelist); } else if (grf_version==0x02) { //****** Grf version 02xx ****** unsigned char eheader[8]; @@ -706,15 +792,15 @@ static int grfio_entryread(char *gfname,int gentry) return 4; } - rBuf = calloc( rSize , 1); // Get a Read Size + rBuf = (unsigned char *)aCallocA( rSize , 1); // Get a Read Size if (rBuf==NULL) { fclose(fp); printf("out of memory : grf compress entry table buffer\n"); return 3; } - grf_filelist = calloc( eSize , 1); // Get a Extend Size + grf_filelist = (unsigned char *)aCallocA( eSize , 1); // Get a Extend Size if (grf_filelist==NULL) { - free(rBuf); + aFree(rBuf); fclose(fp); printf("out of memory : grf extract entry table buffer\n"); return 3; @@ -723,7 +809,7 @@ static int grfio_entryread(char *gfname,int gentry) fclose(fp); decode_zip(grf_filelist,&eSize,rBuf,rSize); // Decode function list_size = eSize; - free(rBuf); + aFree(rBuf); entrys = getlong(grf_header+0x26) - 7; @@ -732,13 +818,14 @@ static int grfio_entryread(char *gfname,int gentry) int ofs2,srclen,srccount,type; FILELIST aentry; - fname = grf_filelist+ofs; + fname = (char*)(grf_filelist+ofs); if (strlen(fname)>sizeof(aentry.fn)-1) { printf("grf : file name too long : %s\n",fname); - free(grf_filelist); + aFree(grf_filelist); exit(1); } - ofs2 = ofs+strlen(grf_filelist+ofs)+1; + //ofs2 = ofs+strlen((char*)(grf_filelist+ofs))+1; + ofs2 = ofs+strlen(fname)+1; type = grf_filelist[ofs2+12]; if(type==1 || type==3 || type==5) { srclen=getlong(grf_filelist+ofs2); @@ -766,7 +853,7 @@ static int grfio_entryread(char *gfname,int gentry) } ofs = ofs2 + 17; } - free(grf_filelist); + aFree(grf_filelist); } else { //****** Grf Other version ****** fclose(fp); @@ -786,11 +873,11 @@ static int grfio_entryread(char *gfname,int gentry) static void grfio_resourcecheck() { int size; - unsigned char *buf,*ptr; + char *buf,*ptr; char w1[256],w2[256],src[256],dst[256]; FILELIST *entry; - buf=grfio_reads("data\\resnametable.txt",&size); + buf = (char*)grfio_reads("data\\resnametable.txt",&size); buf[size] = 0; for(ptr=buf;ptr-buf<size;) { @@ -816,7 +903,7 @@ static void grfio_resourcecheck() if (!ptr) break; ptr++; } - free(buf); + aFree(buf); filelist_adjust(); // Unnecessary area release of filelist } @@ -836,10 +923,11 @@ int grfio_add(char *fname) exit(1); } - printf("%s file reading...\n",fname); +// sprintf(tmp_output,"Reading GRF File: '%s'.\n",fname); +// ShowStatus(tmp_output); if (gentry_entrys>=gentry_maxentry) { - char **new_gentry = (char**)realloc( + char **new_gentry = (char**)aRealloc( (void*)gentry_table,(gentry_maxentry+GENTRY_ADDS)*sizeof(char*) ); if (new_gentry!=NULL) { int lop; @@ -853,7 +941,7 @@ int grfio_add(char *fname) } } len = strlen( fname ); - buf = calloc(len+1, 1); + buf = (char*)aCallocA(len+1, 1); if (buf==NULL) { printf("out of memory : gentry\n"); exit(1); @@ -879,20 +967,30 @@ void grfio_final(void) { int lop; - if (filelist!=NULL) free(filelist); + if (filelist!=NULL) aFree(filelist); filelist = NULL; filelist_entrys = filelist_maxentry = 0; if (gentry_table!=NULL) { for(lop=0;lop<gentry_entrys;lop++) { if (gentry_table[lop]!=NULL) { - free(gentry_table[lop]); + aFree(gentry_table[lop]); } } - free(gentry_table); + aFree(gentry_table); } gentry_table = NULL; gentry_entrys = gentry_maxentry = 0; + +#ifdef _WIN32 + #ifndef LOCALZLIB + DLL_CLOSE(zlib_dll); + zlib_inflateInit_ = NULL; + zlib_inflate = NULL; + zlib_inflateEnd = NULL; + #endif +#endif + } /*========================================== @@ -905,6 +1003,24 @@ void grfio_init(char *fname) char line[1024], w1[1024], w2[1024]; int result = 0, result2 = 0, result3 = 0, result4 = 0; +#ifdef _WIN32 + #ifndef LOCALZLIB + if(!zlib_dll) { + zlib_dll = DLL_OPEN ("zlib.dll"); + DLL_SYM (zlib_inflateInit_, zlib_dll, "inflateInit_"); + DLL_SYM (zlib_inflate, zlib_dll, "inflate"); + DLL_SYM (zlib_inflateEnd, zlib_dll, "inflateEnd"); + DLL_SYM (zlib_deflateInit_, zlib_dll, "deflateInit_"); + DLL_SYM (zlib_deflate, zlib_dll, "deflate"); + DLL_SYM (zlib_deflateEnd, zlib_dll, "deflateEnd"); + if(zlib_dll == NULL) { + MessageBox(NULL,"Can't load zlib.dll","grfio.c",MB_OK); + exit(1); + } + } + #endif +#endif + data_conf = fopen(fname, "r"); // It will read, if there is grf-files.txt. @@ -923,7 +1039,8 @@ void grfio_init(char *fname) } fclose(data_conf); - printf("read %s done\n",fname); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n",fname); + ShowStatus(tmp_output); } // end of reading grf-files.txt hashinit(); // hash table initialization @@ -945,9 +1062,9 @@ void grfio_init(char *fname) if (strcmp(data_dir, "") == 0) // Id data_dir doesn't exist result4 = 1; // Data directory - +/* if (result != 0 && result2 != 0 && result3 != 0 && result4 != 0) { printf("not grf file readed exit!!\n"); exit(1); // It ends, if a resource cannot read one. - } + }*/ } diff --git a/src/common/grfio.h b/src/common/grfio.h index 53b9da8d4..3fa257e2f 100644 --- a/src/common/grfio.h +++ b/src/common/grfio.h @@ -8,6 +8,9 @@ void* grfio_read(char*); // GRFIO data file read void* grfio_reads(char*,int*); // GRFIO data file read & size get int grfio_size(char*); // GRFIO data file size get +int decode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); +int encode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); + // Accessor to GRF filenames char *grfio_setdatafile(const char *str); char *grfio_setadatafile(const char *str); diff --git a/src/common/lock.c b/src/common/lock.c index 9a2205bf4..0258cbd2c 100644 --- a/src/common/lock.c +++ b/src/common/lock.c @@ -1,37 +1,55 @@ #include <stdio.h> +#include <errno.h> +#include <string.h> +#ifndef WIN32 +#include <unistd.h> +#else +#include <windows.h> +#define F_OK 0x0 +#define R_OK 0x4 +#endif #include "lock.h" +#include "showmsg.h" +#define exists(filename) (!access(filename, F_OK)) // ‘‚«ž‚݃tƒ@ƒCƒ‹‚̕ی숗 // i‘‚«ž‚Ý‚ªI‚í‚é‚Ü‚ÅA‹Œƒtƒ@ƒCƒ‹‚ð•ÛŠÇ‚µ‚Ä‚¨‚j // V‚µ‚¢ƒtƒ@ƒCƒ‹‚Ì‘‚«ž‚ÝŠJŽn -FILE* lock_fopen(const char* filename,int *info) { +FILE* lock_fopen (const char* filename, int *info) { char newfile[512]; FILE *fp; - int no = 0; + int no = 0; // ˆÀ‘S‚ȃtƒ@ƒCƒ‹–¼‚𓾂éiŽè”²‚«j do { - sprintf(newfile,"%s_%04d.tmp",filename,++no); - } while((fp = fopen(newfile,"r")) && (fclose(fp), no<9999) ); + sprintf(newfile, "%s_%04d.tmp", filename, ++no); + } while((fp = fopen(newfile,"r")) && (fclose(fp), no < 9999)); *info = no; return fopen(newfile,"w"); } // ‹Œƒtƒ@ƒCƒ‹‚ð휕Vƒtƒ@ƒCƒ‹‚ðƒŠƒl[ƒ€ -int lock_fclose(FILE *fp,const char* filename,int *info) { - int ret = 0; +int lock_fclose (FILE *fp, const char* filename, int *info) { + int ret = 1; char newfile[512]; - if(fp != NULL) { + char oldfile[512]; + if (fp != NULL) { ret = fclose(fp); - sprintf(newfile,"%s_%04d.tmp",filename,*info); - remove(filename); + sprintf(newfile, "%s_%04d.tmp", filename, *info); + sprintf(oldfile, "%s.bak", filename); // old backup file + + if (exists(oldfile)) remove(oldfile); // remove backup file if it already exists + rename (filename, oldfile); // backup our older data instead of deleting it + // ‚±‚̃^ƒCƒ~ƒ“ƒO‚Å—Ž‚¿‚é‚ÆÅˆ«B - rename(newfile,filename); - return ret; - } else { - return 1; + if ((ret = rename(newfile,filename)) != 0) { // rename our temporary file to its correct name + sprintf(tmp_output,"%s - '"CL_WHITE"%s"CL_RESET"'\n", strerror(errno), newfile); + ShowError(tmp_output); + } } + + return ret; } diff --git a/src/common/malloc.c b/src/common/malloc.c index eda9bc218..b81c25ed5 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -1,13 +1,27 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "malloc.h" +#ifdef MEMWATCH +#include "memwatch.h" +#endif + +// “ÆŽ©ƒƒ‚ƒŠƒ}ƒl[ƒWƒƒ‚ðŽg—p‚·‚éê‡AŽŸ‚̃Rƒƒ“ƒg‚ðŠO‚µ‚Ä‚‚¾‚³‚¢B +//#define USE_MEMMGR + +#if !defined(DMALLOC) && !defined(GCOLLECT) && !defined(BCHECK) && !defined(USE_MEMMGR) + void* aMalloc_( size_t size, const char *file, int line, const char *func ) { void *ret; - + // printf("%s:%d: in func %s: malloc %d\n",file,line,func,size); +#ifdef MEMWATCH + ret=mwMalloc(size,file,line); +#else ret=malloc(size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: malloc error out of memory!\n",file,line,func); exit(1); @@ -18,9 +32,13 @@ void* aMalloc_( size_t size, const char *file, int line, const char *func ) void* aCalloc_( size_t num, size_t size, const char *file, int line, const char *func ) { void *ret; - + // printf("%s:%d: in func %s: calloc %d %d\n",file,line,func,num,size); +#ifdef MEMWATCH + ret=mwCalloc(num,size,file,line); +#else ret=calloc(num,size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: calloc error out of memory!\n",file,line,func); exit(1); @@ -32,9 +50,13 @@ void* aCalloc_( size_t num, size_t size, const char *file, int line, const char void* aRealloc_( void *p, size_t size, const char *file, int line, const char *func ) { void *ret; - + // printf("%s:%d: in func %s: realloc %p %d\n",file,line,func,p,size); +#ifdef MEMWATCH + ret=mwRealloc(p,size,file,line); +#else ret=realloc(p,size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: realloc error out of memory!\n",file,line,func); exit(1); @@ -42,3 +64,485 @@ void* aRealloc_( void *p, size_t size, const char *file, int line, const char *f } return ret; } + +char* aStrdup_( const void *p, const char *file, int line, const char *func ) +{ + char *ret; + + // printf("%s:%d: in func %s: strdup %p\n",file,line,func,p); +#ifdef MEMWATCH + ret=mwStrdup(p,file,line); +#else + ret= strdup((char *) p); +#endif + if(ret==NULL){ + printf("%s:%d: in func %s: strdup error out of memory!\n",file,line,func); + exit(1); + + } + return ret; +} + +void aFree_( void *p, const char *file, int line, const char *func ) +{ + // printf("%s:%d: in func %s: free %p\n",file,line,func,p); +#ifdef MEMWATCH + mwFree(p,file,line); +#else + free(p); +#endif +} + +#elif defined(GCOLLECT) + +void * _bcallocA(size_t size, size_t cnt) { + void *ret = aMallocA(size * cnt); + memset(ret, 0, size * cnt); + return ret; +} + +void * _bcalloc(size_t size, size_t cnt) { + void *ret = aMalloc(size * cnt); + memset(ret, 0, size * cnt); + return ret; +} + +char * _bstrdup(const char *chr) { + int len = strlen(chr); + char *ret = (char*)aMalloc(len + 1); + strcpy(ret, chr); + return ret; +} + +#elif defined(USE_MEMMGR) + +/* USE_MEMMGR */ + +/* + * ƒƒ‚ƒŠƒ}ƒl[ƒWƒƒ + * malloc , free ‚̈—‚ðŒø—¦“I‚Éo—ˆ‚邿‚¤‚É‚µ‚½‚à‚ÌB + * •¡ŽG‚Ȉ—‚ðs‚Á‚Ä‚¢‚é‚Ì‚ÅAŽáбd‚‚Ȃ邩‚à‚µ‚ê‚Ü‚¹‚ñB + * + * ƒf[ƒ^\‘¢‚È‚Çià–¾‰ºŽè‚Å‚·‚¢‚Ü‚¹‚ñ^^; j + * Eƒƒ‚ƒŠ‚ð•¡”‚ÌuƒuƒƒbƒNv‚É•ª‚¯‚ÄA‚³‚ç‚ɃuƒƒbƒN‚ð•¡”‚Ìuƒ†ƒjƒbƒgv + * ‚É•ª‚¯‚Ä‚¢‚Ü‚·Bƒ†ƒjƒbƒg‚̃TƒCƒY‚ÍA‚PƒuƒƒbƒN‚Ì—e—ʂ𕡔ŒÂ‚ɋϓ™”z•ª + * ‚µ‚½‚à‚̂ł·B‚½‚Æ‚¦‚ÎA‚Pƒ†ƒjƒbƒg32KB‚Ìê‡AƒuƒƒbƒN‚P‚‚Í32Byte‚̃† + * ƒjƒbƒg‚ªA1024ŒÂW‚Ü‚Á‚Äo—ˆ‚Ä‚¢‚½‚èA64Byte‚̃†ƒjƒbƒg‚ª 512ŒÂW‚Ü‚Á‚Ä + * o—ˆ‚Ä‚¢‚½‚肵‚Ü‚·Bipadding,unit_head ‚ðœ‚j + * + * Eƒ†ƒjƒbƒg“¯Žm‚ÍƒŠƒ“ƒNƒŠƒXƒg(block_prev,block_next) ‚ł‚Ȃª‚èA“¯‚¶ƒTƒC + * ƒY‚ðŽ‚Âƒ†ƒjƒbƒg“¯Žm‚àƒŠƒ“ƒNƒŠƒXƒg(samesize_prev,samesize_nect) ‚Å‚Â‚È + * ‚ª‚Á‚Ä‚¢‚Ü‚·B‚»‚ê‚É‚æ‚èA•s—v‚ƂȂÁ‚½ƒƒ‚ƒŠ‚ÌÄ—˜—p‚ªŒø—¦“I‚És‚¦‚Ü‚·B + */ + +/* ƒuƒƒbƒN‚É“ü‚éƒf[ƒ^—Ê */ +#define BLOCK_DATA_SIZE 80*1024 + +/* ˆê“x‚ÉŠm•Û‚·‚éƒuƒƒbƒN‚Ì”B */ +#define BLOCK_ALLOC 32 + +/* ƒuƒƒbƒN‚̃Aƒ‰ƒCƒƒ“ƒg */ +#define BLOCK_ALIGNMENT 64 + +/* ƒuƒƒbƒN */ +struct block { + int block_no; /* ƒuƒƒbƒN”Ô† */ + struct block* block_prev; /* ‘O‚ÉŠm•Û‚µ‚½—̈æ */ + struct block* block_next; /* ŽŸ‚ÉŠm•Û‚µ‚½—̈æ */ + int samesize_no; /* “¯‚¶ƒTƒCƒY‚̔Ԇ */ + struct block* samesize_prev; /* “¯‚¶ƒTƒCƒY‚Ì‘O‚̗̈æ */ + struct block* samesize_next; /* “¯‚¶ƒTƒCƒY‚ÌŽŸ‚̗̈æ */ + int unit_size; /* ƒ†ƒjƒbƒg‚̃oƒCƒg” 0=–¢Žg—p */ + int unit_hash; /* ƒ†ƒjƒbƒg‚̃nƒbƒVƒ… */ + int unit_count; /* ƒ†ƒjƒbƒg‚Ì” */ + int unit_used; /* Žg—pς݃†ƒjƒbƒg */ + char data[BLOCK_DATA_SIZE]; +}; + +struct unit_head { + struct block* block; + int size; + const char* file; + int line; +}; + +static struct block* block_first = NULL; +static struct block* block_last = NULL; +static struct block* block_unused = NULL; + +/* ƒ†ƒjƒbƒg‚ւ̃nƒbƒVƒ…B80KB/64Byte = 1280ŒÂ */ +static struct block* unit_first[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* ʼn */ +static struct block* unit_unfill[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* –„‚Ü‚Á‚ĂȂ¢ */ +static struct block* unit_last[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* ÅŒã */ + +/* ƒƒ‚ƒŠ‚ðŽg‚¢‰ñ‚¹‚È‚¢—̈æ—p‚̃f[ƒ^ */ +struct unit_head_large { + struct unit_head_large* prev; + struct unit_head_large* next; + struct unit_head unit_head; +}; +static struct unit_head_large *unit_head_large_first = NULL; + +static struct block* block_malloc(void); +static void block_free(struct block* p); +static void memmgr_info(void); + +void* aMalloc_(size_t size, const char *file, int line, const char *func ) { + int i; + struct block *block; + int size_hash = (size+BLOCK_ALIGNMENT-1) / BLOCK_ALIGNMENT; + size = size_hash * BLOCK_ALIGNMENT; /* ƒAƒ‰ƒCƒƒ“ƒg‚Ì”{”‚ÉØ‚èã‚° */ + + if(size == 0) { + return NULL; + } + + /* ƒuƒƒbƒN’·‚ð’´‚¦‚é—̈æ‚ÌŠm•Û‚É‚ÍAmalloc() ‚ð—p‚¢‚é */ + /* ‚»‚ÌÛAunit_head.block ‚É NULL ‚ð‘ã“ü‚µ‚Ä‹æ•Ê‚·‚é */ + if(size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { +#ifdef MEMWATCH + struct unit_head_large* p = (struct unit_head_large*)mwMalloc(sizeof(struct unit_head_large) + size,file,line); +#else + struct unit_head_large* p = (struct unit_head_large*)malloc(sizeof(struct unit_head_large) + size); +#endif + if(p != NULL) { + p->unit_head.block = NULL; + p->unit_head.size = size; + p->unit_head.file = file; + p->unit_head.line = line; + if(unit_head_large_first == NULL) { + unit_head_large_first = p; + p->next = NULL; + p->prev = NULL; + } else { + unit_head_large_first->prev = p; + p->prev = NULL; + p->next = unit_head_large_first; + unit_head_large_first = p; + } + return (char *)p + sizeof(struct unit_head_large); + } else { + printf("MEMMGR::memmgr_alloc failed.\n"); + exit(1); + } + } + + /* “¯ˆêƒTƒCƒY‚̃uƒƒbƒN‚ªŠm•Û‚³‚ê‚Ä‚¢‚È‚¢ŽžAV‚½‚ÉŠm•Û‚·‚é */ + if(unit_unfill[size_hash] == NULL) { + block = block_malloc(); + if(unit_first[size_hash] == NULL) { + /* ‰‰ñŠm•Û */ + unit_first[size_hash] = block; + unit_last[size_hash] = block; + block->samesize_no = 0; + block->samesize_prev = NULL; + block->samesize_next = NULL; + } else { + /* ˜AŒ‹ì‹Æ */ + unit_last[size_hash]->samesize_next = block; + block->samesize_no = unit_last[size_hash]->samesize_no + 1; + block->samesize_prev = unit_last[size_hash]; + block->samesize_next = NULL; + unit_last[size_hash] = block; + } + unit_unfill[size_hash] = block; + block->unit_size = size + sizeof(struct unit_head); + block->unit_count = BLOCK_DATA_SIZE / block->unit_size; + block->unit_used = 0; + block->unit_hash = size_hash; + /* –¢Žg—pFlag‚ð—§‚Ä‚é */ + for(i=0;i<block->unit_count;i++) { + ((struct unit_head*)(&block->data[block->unit_size * i]))->block = NULL; + } + } + /* ƒ†ƒjƒbƒgŽg—pŒÂ”‰ÁŽZ */ + block = unit_unfill[size_hash]; + block->unit_used++; + + /* ƒ†ƒjƒbƒg“à‚ð‘S‚ÄŽg‚¢‰Ê‚½‚µ‚½ */ + if(block->unit_count == block->unit_used) { + do { + unit_unfill[size_hash] = unit_unfill[size_hash]->samesize_next; + } while( + unit_unfill[size_hash] != NULL && + unit_unfill[size_hash]->unit_count == unit_unfill[size_hash]->unit_used + ); + } + + /* ƒuƒƒbƒN‚Ì’†‚̋󂫃†ƒjƒbƒg‘{õ */ + for(i=0;i<block->unit_count;i++) { + struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]); + if(head->block == NULL) { + head->block = block; + head->size = size; + head->line = line; + head->file = file; + return (char *)head + sizeof(struct unit_head); + } + } + // ‚±‚±‚É—ˆ‚Ă͂¢‚¯‚È‚¢B + printf("MEMMGR::memmgr_malloc() serious error.\n"); + memmgr_info(); + exit(1); + return NULL; +}; + +void* aCalloc_(size_t num, size_t size, const char *file, int line, const char *func ) { + void *p = aMalloc_(num * size,file,line,func); + memset(p,0,num * size); + return p; +} + +void* aRealloc_(void *memblock, size_t size, const char *file, int line, const char *func ) { + size_t old_size; + if(memblock == NULL) { + return aMalloc_(size,file,line,func); + } + + old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head)))->size; + if(old_size > size) { + // ƒTƒCƒYk¬ -> ‚»‚̂܂ܕԂ·iŽè”²‚«j + return memblock; + } else { + // ƒTƒCƒYŠg‘å + void *p = aMalloc_(size,file,line,func); + if(p != NULL) { + memcpy(p,memblock,old_size); + } + aFree_(memblock,file,line,func); + return p; + } +} + +char* aStrdup_(const void *p, const char *file, int line, const char *func ) { + if(p == NULL) { + return NULL; + } else { + int len = strlen(p); + char *string = (char *)aMalloc_(len + 1,file,line,func); + memcpy(string,p,len+1); + return string; + } +} + +void aFree_(void *ptr, const char *file, int line, const char *func ) { + struct unit_head *head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head)); + if(ptr == NULL) { + return; + } else if(head->block == NULL && head->size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { + /* malloc() ‚Å’¼‚ÉŠm•Û‚³‚ꂽ—̈æ */ + struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large)); + if(head_large->prev) { + head_large->prev->next = head_large->next; + } else { + unit_head_large_first = head_large->next; + } + if(head_large->next) { + head_large->next->prev = head_large->prev; + } + free(head_large); + return; + } else { + /* ƒ†ƒjƒbƒg‰ð•ú */ + struct block *block = head->block; + if(head->block == NULL) { + printf("memmgr: args of aFree is freed pointer %s line %d\n",file,line); + } else { + head->block = NULL; + if(--block->unit_used == 0) { + /* ƒuƒƒbƒN‚̉ð•ú */ + if(unit_unfill[block->unit_hash] == block) { + /* ‹ó‚«ƒ†ƒjƒbƒg‚ÉŽw’肳‚ê‚Ä‚¢‚é */ + do { + unit_unfill[block->unit_hash] = unit_unfill[block->unit_hash]->samesize_next; + } while( + unit_unfill[block->unit_hash] != NULL && + unit_unfill[block->unit_hash]->unit_count == unit_unfill[block->unit_hash]->unit_used + ); + } + if(block->samesize_prev == NULL && block->samesize_next == NULL) { + /* “Æ—§ƒuƒƒbƒN‚̉ð•ú */ + unit_first[block->unit_hash] = NULL; + unit_last[block->unit_hash] = NULL; + unit_unfill[block->unit_hash] = NULL; + } else if(block->samesize_prev == NULL) { + /* 擪ƒuƒƒbƒN‚̉ð•ú */ + unit_first[block->unit_hash] = block->samesize_next; + (block->samesize_next)->samesize_prev = NULL; + } else if(block->samesize_next == NULL) { + /* ––’[ƒuƒƒbƒN‚̉ð•ú */ + unit_last[block->unit_hash] = block->samesize_prev; + (block->samesize_prev)->samesize_next = NULL; + } else { + /* ’†ŠÔƒuƒƒbƒN‚̉ð•ú */ + (block->samesize_next)->samesize_prev = block->samesize_prev; + (block->samesize_prev)->samesize_next = block->samesize_next; + } + block_free(block); + } else { + /* ‹ó‚«ƒ†ƒjƒbƒg‚ÌÄÝ’è */ + if( + unit_unfill[block->unit_hash] == NULL || + unit_unfill[block->unit_hash]->samesize_no > block->samesize_no + ) { + unit_unfill[block->unit_hash] = block; + } + } + } + } +} + +/* Œ»Ý‚Ì󋵂ð•\ަ‚·‚é */ +static void memmgr_info(void) { + int i; + struct block *p; + printf("** Memory Maneger Information **\n"); + if(block_first == NULL) { + printf("Uninitialized.\n"); + return; + } + printf( + "Blocks: %04u , BlockSize: %06u Byte , Used: %08uKB\n", + block_last->block_no+1,sizeof(struct block), + (block_last->block_no+1) * sizeof(struct block) / 1024 + ); + p = block_first; + for(i=0;i<=block_last->block_no;i++) { + printf(" Block #%04u : ",p->block_no); + if(p->unit_size == 0) { + printf("unused.\n"); + } else { + printf( + "size: %05u byte. used: %04u/%04u prev:", + p->unit_size - sizeof(struct unit_head),p->unit_used,p->unit_count + ); + if(p->samesize_prev == NULL) { + printf("NULL"); + } else { + printf("%04u",(p->samesize_prev)->block_no); + } + printf(" next:"); + if(p->samesize_next == NULL) { + printf("NULL"); + } else { + printf("%04u",(p->samesize_next)->block_no); + } + printf("\n"); + } + p = p->block_next; + } +} + +/* ƒuƒƒbƒN‚ðŠm•Û‚·‚é */ +static struct block* block_malloc(void) { + if(block_unused != NULL) { + /* ƒuƒƒbƒN—p‚̗̈æ‚ÍŠm•ÛÏ‚Ý */ + struct block* ret = block_unused; + do { + block_unused = block_unused->block_next; + } while(block_unused != NULL && block_unused->unit_size != 0); + return ret; + } else { + /* ƒuƒƒbƒN—p‚̗̈æ‚ðV‚½‚ÉŠm•Û‚·‚é */ + int i; + int block_no; + struct block* p = (struct block *)calloc(sizeof(struct block),BLOCK_ALLOC); + if(p == NULL) { + printf("MEMMGR::block_alloc failed.\n"); + exit(1); + } + if(block_first == NULL) { + /* ‰‰ñŠm•Û */ + block_no = 0; + block_first = p; + } else { + block_no = block_last->block_no + 1; + block_last->block_next = p; + p->block_prev = block_last; + } + block_last = &p[BLOCK_ALLOC - 1]; + /* ƒuƒƒbƒN‚ð˜AŒ‹‚³‚¹‚é */ + for(i=0;i<BLOCK_ALLOC;i++) { + if(i != 0) { + p[i].block_prev = &p[i-1]; + } + if(i != BLOCK_ALLOC -1) { + p[i].block_next = &p[i+1]; + } + p[i].block_no = block_no + i; + } + + /* –¢Žg—pƒuƒƒbƒN‚ւ̃|ƒCƒ“ƒ^‚ðXV */ + block_unused = &p[1]; + p->unit_size = 1; + return p; + } +} + +static void block_free(struct block* p) { + /* free() ‚¹‚¸‚ÉA–¢Žg—pƒtƒ‰ƒO‚ð•t‚¯‚邾‚¯ */ + p->unit_size = 0; + /* –¢Žg—pƒ|ƒCƒ“ƒ^[‚ðXV‚·‚é */ + if(block_unused == NULL) { + block_unused = p; + } else if(block_unused->block_no > p->block_no) { + block_unused = p; + } +} + +static char memmer_logfile[128]; + +static FILE* memmgr_log(void) { + FILE *fp = fopen(memmer_logfile,"w"); + if(!fp) { fp = stdout; } + fprintf(fp,"memmgr: memory leaks found\n"); + return fp; +} + +static void memmer_exit(void) { + FILE *fp = NULL; + int i; + int count = 0; + struct block *block = block_first; + struct unit_head_large *large = unit_head_large_first; + while(block) { + if(block->unit_size) { + if(!fp) { fp = memmgr_log(); } + for(i=0;i<block->unit_count;i++) { + struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]); + if(head->block != NULL) { + fprintf( + fp,"%04d : %s line %d size %d\n",++count, + head->file,head->line,head->size + ); + } + } + } + block = block->block_next; + } + while(large) { + if(!fp) { fp = memmgr_log(); } + fprintf( + fp,"%04d : %s line %d size %d\n",++count, + large->unit_head.file, + large->unit_head.line,large->unit_head.size + ); + large = large->next; + } + if(!fp) { + printf("memmgr: no memory leaks found.\n"); + } else { + printf("memmgr: memory leaks found.\n"); + fclose(fp); + } +} +#endif + +int do_init_memmgr(const char* file) { + #ifdef USE_MEMMGR + sprintf(memmer_logfile,"%s.log",file); + atexit(memmer_exit); + printf("memmgr: initialised: %s\n",memmer_logfile); + #endif + return 0; +} diff --git a/src/common/malloc.h b/src/common/malloc.h index 3733a5e55..c233adb8d 100644 --- a/src/common/malloc.h +++ b/src/common/malloc.h @@ -3,6 +3,49 @@ #include <stdlib.h> +#if defined(DMALLOC) + +# include "dmalloc.h" +# define aMalloc(size) \ + dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MALLOC, 0, 0) +# define aMallocA(size) \ + dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MALLOC, 0, 0) +# define aCallocA(count,size) \ + dmalloc_malloc(__FILE__, __LINE__, (count)*(size), DMALLOC_FUNC_CALLOC, 0, 0) +# define aCalloc(count,size) \ + dmalloc_malloc(__FILE__, __LINE__, (count)*(size), DMALLOC_FUNC_CALLOC, 0, 0) +# define aRealloc(ptr,size) \ + dmalloc_realloc(__FILE__, __LINE__, (ptr), (size), DMALLOC_FUNC_REALLOC, 0) +# define aFree(ptr) free(ptr) +# define aStrdup(ptr) strdup(ptr) + +#elif defined(GCOLLECT) + +# include "gc.h" +# define aMalloc(n) GC_MALLOC(n) +# define aMallocA(n) GC_MALLOC_ATOMIC(n) +# define aCallocA(m,n) _bcallocA(m,n) +# define aCalloc(m,n) _bcalloc(m,n) +# define aRealloc(p,n) GC_REALLOC(p,n) +# define aFree(n) GC_FREE(n) +# define aStrdup(n) _bstrdup(n) + + extern void * _bcalloc(size_t, size_t); + extern void * _bcallocA(size_t, size_t); + extern char * _bstrdup(const char *); + +#elif defined(BCHECK) + +# define aMalloc(n) malloc(n) +# define aMallocA(n) malloc(n) +# define aCalloc(m,n) calloc(m,n) +# define aCallocA(m,n) calloc(m,n) +# define aRealloc(p,n) realloc(p,n) +# define aFree(n) free(n) +# define aStrdup(n) strdup(n) + +#else + #if __STDC_VERSION__ < 199901L # if __GNUC__ >= 2 # define __func__ __FUNCTION__ @@ -11,15 +54,24 @@ # endif #endif -#define ALC_MARK __FILE__, __LINE__, __func__ +# define ALC_MARK __FILE__, __LINE__, __func__ -void* aMalloc_( size_t size, const char *file, int line, const char *func ); -void* aCalloc_( size_t num, size_t size, const char *file, int line, const char *func ); -void* aRealloc_( void *p, size_t size, const char *file, int line, const char *func ); + void* aMalloc_( size_t size, const char *file, int line, const char *func ); + void* aCalloc_( size_t num, size_t size, const char *file, int line, const char *func ); + void* aRealloc_( void *p, size_t size, const char *file, int line, const char *func ); + void aFree_( void *p, const char *file, int line, const char *func ); + char* aStrdup_( const void *p, const char *file, int line, const char *func ); -#define aMalloc(n) aMalloc_(n,ALC_MARK) -#define aCalloc(m,n) aCalloc_(m,n,ALC_MARK) -#define aRealloc(p,n) aRealloc_(p,n,ALC_MARK) +# define aMalloc(n) aMalloc_(n,ALC_MARK) +# define aMallocA(n) aMalloc_(n,ALC_MARK) +# define aCalloc(m,n) aCalloc_(m,n,ALC_MARK) +# define aCallocA(m,n) aCalloc_(m,n,ALC_MARK) +# define aRealloc(p,n) aRealloc_(p,n,ALC_MARK) +# define aStrdup(p) aStrdup_(p,ALC_MARK) +# define aFree(p) do { aFree_(p,ALC_MARK); if(p != NULL) { p = NULL; } } while(0) + +#endif +int do_init_memmgr(const char* file); #endif diff --git a/src/common/mmo.h b/src/common/mmo.h index f6150d39a..1602c5655 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -7,6 +7,20 @@ #include <time.h> #include "utils.h" // _WIN32 +#if ! defined(Assert) +#if defined(RELEASE) +#define Assert(EX) +#else +// extern "C" { +#include <assert.h> +// } +#if defined(_WIN32) +#include <crtdbg.h> +#endif +#define Assert(EX) assert(EX) +#endif +#endif /* ! defined(Assert) */ + #ifdef CYGWIN // txt‚âlog‚Ȃǂ̑‚«o‚·ƒtƒ@ƒCƒ‹‚̉üsƒR[ƒh #define RETCODE "\r\n" // (CR/LFFWindowsŒn) @@ -29,7 +43,7 @@ #define MAX_AMOUNT 30000 #define MAX_ZENY 1000000000 // 1G zeny #define MAX_CART 100 -#define MAX_SKILL 450 +#define MAX_SKILL 650 #define GLOBAL_REG_NUM 96 #define ACCOUNT_REG_NUM 16 #define ACCOUNT_REG2_NUM 16 @@ -39,7 +53,7 @@ #define MAX_STORAGE 300 #define MAX_GUILD_STORAGE 1000 #define MAX_PARTY 12 -#define MAX_GUILD 36 // increased max guild members to accomodate for +2 increase for extension levels [Valaris] (removed) [PoW] +#define MAX_GUILD 16+10*6 // increased max guild members to accomodate for +6 increase for extension levels [Lupus] #define MAX_GUILDPOSITION 20 // increased max guild positions to accomodate for all members [Valaris] (removed) [PoW] #define MAX_GUILDEXPLUSION 32 #define MAX_GUILDALLIANCE 16 @@ -54,8 +68,6 @@ #define MIN_CLOTH_COLOR battle_config.min_cloth_color #define MAX_CLOTH_COLOR battle_config.max_cloth_color -#define MIN_CHAR_ID 150000 // shouldn't ever be changed, the client requires this min value [Ajarn] - // for produce #define MIN_ATTRIBUTE 0 #define MAX_ATTRIBUTE 4 @@ -102,7 +114,7 @@ struct s_pet { int account_id; int char_id; int pet_id; - short class; + short class_; short level; short egg_id;//pet egg id short equip;//pet equip name_id @@ -117,10 +129,13 @@ struct mmo_charstatus { int char_id; int account_id; int partner_id; + int father; + int mother; + int child; int base_exp,job_exp,zeny; - short class; + short class_; short status_point,skill_point; int hp,max_hp,sp,max_sp; short option,karma,manner; @@ -131,7 +146,7 @@ struct mmo_charstatus { short head_top,head_mid,head_bottom; char name[24]; - unsigned char base_level,job_level; + unsigned int base_level,job_level; short str,agi,vit,int_,dex,luk; unsigned char char_num,sex; @@ -154,17 +169,18 @@ struct mmo_charstatus { }; struct storage { + int dirty; int account_id; short storage_status; short storage_amount; - struct item storage[MAX_STORAGE]; + struct item storage_[MAX_STORAGE]; }; struct guild_storage { int guild_id; short storage_status; short storage_amount; - struct item storage[MAX_GUILD_STORAGE]; + struct item storage_[MAX_GUILD_STORAGE]; }; struct map_session_data; @@ -185,13 +201,13 @@ struct party { int party_id; char name[24]; int exp; - int item; + int item, itemc; struct party_member member[MAX_PARTY]; }; struct guild_member { int account_id, char_id; - short hair,hair_color,gender,class,lv; + short hair,hair_color,gender,class_,lv; int exp,exp_payper; short online,position; int rsv1,rsv2; @@ -267,8 +283,8 @@ struct guild_castle { int Ghp4; int Ghp5; int Ghp6; - int Ghp7; - int GID0; + int Ghp7; + int GID0; int GID1; int GID2; int GID3; @@ -313,23 +329,25 @@ enum { GD_DEVELOPMENT=10014, }; -#ifndef _WIN32 -#ifndef strcmpi -#define strcmpi strcasecmp -#endif -#ifndef stricmp -#define stricmp strcasecmp -#endif -#ifndef strncmpi -#define strncmpi strncasecmp -#endif -#ifndef strnicmp -#define strnicmp strncasecmp -#endif -#ifndef strrchr -#define strrchr rindex -#endif - +#ifndef __WIN32 + #ifndef strcmpi + #define strcmpi strcasecmp + #endif + #ifndef stricmp + #define stricmp strcasecmp + #endif + #ifndef strncmpi + #define strncmpi strncasecmp + #endif + #ifndef strnicmp + #define strnicmp strncasecmp + #endif +#else + #define snprintf _snprintf + #define vsnprintf _vsnprintf + #ifndef strncmpi + #define strncmpi strnicmp + #endif #endif #endif // _MMO_H_ diff --git a/src/common/nullpo.h b/src/common/nullpo.h index 11283f941..0b9a9f7a5 100644 --- a/src/common/nullpo.h +++ b/src/common/nullpo.h @@ -87,6 +87,8 @@ #define nullpo_retr(ret, t) \ if (nullpo_chk(NLP_MARK, (void *)(t))) {return(ret);} +#define nullpo_retb(t) \ + if (nullpo_chk(NLP_MARK, (void *)(t))) {break;} // ‰Â•ψø”ƒ}ƒNƒ‚ÉŠÖ‚·‚éðŒƒRƒ“ƒpƒCƒ‹ #if __STDC_VERSION__ >= 199901L @@ -100,6 +102,9 @@ #define nullpo_retr_f(ret, t, fmt, ...) \ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {return(ret);} +#define nullpo_retb_f(t, fmt, ...) \ + if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {break;} + #elif __GNUC__ >= 2 /* GCC—p */ #define nullpo_ret_f(t, fmt, args...) \ @@ -111,6 +116,9 @@ #define nullpo_retr_f(ret, t, fmt, args...) \ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {return(ret);} +#define nullpo_retb_f(t, fmt, args...) \ + if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {break;} + #else /* ‚»‚Ì‘¼‚Ìê‡EEE orz */ @@ -127,6 +135,7 @@ #define nullpo_ret(t) if((t)){;} #define nullpo_retv(t) if((t)){;} #define nullpo_retr(ret, t) if((t)){;} +#define nullpo_retb(t) if((t)){;} // ‰Â•ψø”ƒ}ƒNƒ‚ÉŠÖ‚·‚éðŒƒRƒ“ƒpƒCƒ‹ #if __STDC_VERSION__ >= 199901L @@ -134,12 +143,14 @@ #define nullpo_ret_f(t, fmt, ...) if((t)){;} #define nullpo_retv_f(t, fmt, ...) if((t)){;} #define nullpo_retr_f(ret, t, fmt, ...) if((t)){;} +#define nullpo_retb_f(t, fmt, ...) if((t)){;} #elif __GNUC__ >= 2 /* GCC—p */ #define nullpo_ret_f(t, fmt, args...) if((t)){;} #define nullpo_retv_f(t, fmt, args...) if((t)){;} #define nullpo_retr_f(ret, t, fmt, args...) if((t)){;} +#define nullpo_retb_f(t, fmt, args...) if((t)){;} #else /* ‚»‚Ì‘¼‚Ìê‡EEE orz */ diff --git a/src/common/showmsg.c b/src/common/showmsg.c index b65181f3a..24d51d2dc 100644 --- a/src/common/showmsg.c +++ b/src/common/showmsg.c @@ -1,65 +1,68 @@ #include <stdio.h> -#include <stdlib.h> #include <string.h> +#include <stdarg.h> #include "showmsg.h" char tmp_output[1024] = {"\0"}; -int _ShowMessage(const char *string, enum msg_type flag){ // by MC Cameri - /* - _ShowMessage MUST be used instead of printf as of 10/24/2004. - Return: 0 = Successful, 1 = Failed. - */ +// by MC Cameri +int _vShowMessage(enum msg_type flag, const char *string, va_list ap) +{ + // _ShowMessage MUST be used instead of printf as of 10/24/2004. + // Return: 0 = Successful, 1 = Failed. // int ret = 0; char prefix[40]; - char *output; - if (strlen(string) <= 0) { - ShowError("Empty string passed to ShowMessage().\n"); + + if (!string || strlen(string) <= 0) { + printf("Empty string passed to _ShowMessage().\n"); return 1; } switch (flag) { + case MSG_NONE: // direct printf replacement + break; case MSG_STATUS: //Bright Green (To inform about good things) - strcpy(prefix,"\033[1;32m[Status]\033[0;0m: "); + strcpy(prefix,CL_GREEN"[Status]"CL_RESET":"); break; -/* //Do we really need this now? [MC Cameri] case MSG_SQL: //Bright Violet (For dumping out anything related with SQL) - strcpy(prefix,"\033[1;35m[SQL]\033[0;0m: "); + strcpy(prefix,CL_MAGENTA"[SQL]"CL_RESET":"); break; -*/ - case MSG_INFORMATION: //Bright Blue (Variable information) - strcpy(prefix,"\033[1;34m[Info]\033[0;0m: "); + case MSG_INFORMATION: //Bright White (Variable information) + strcpy(prefix,CL_WHITE"[Info]"CL_RESET":"); break; case MSG_NOTICE: //Bright White (Less than a warning) - strcpy(prefix,"\033[1;29m[Notice]\033[0;0m: "); + strcpy(prefix,CL_WHITE"[Notice]"CL_RESET":"); break; case MSG_WARNING: //Bright Yellow - strcpy(prefix,"\033[1;33m[Warning]\033[0;0m: "); + strcpy(prefix,CL_YELLOW"[Warning]"CL_RESET":"); + break; + case MSG_DEBUG: //Bright Cyan, important stuff! + strcpy(prefix,CL_CYAN"[Debug]"CL_RESET":"); break; case MSG_ERROR: //Bright Red (Regular errors) - strcpy(prefix,"\033[1;31m[Error]\033[0;0m: "); + strcpy(prefix,CL_RED"[Error]"CL_RESET":"); break; case MSG_FATALERROR: //Bright Red (Fatal errors, abort(); if possible) - strcpy(prefix,"\033[1;31m[Fatal Error]\033[0;0m: "); + strcpy(prefix,CL_RED"[Fatal Error]"CL_RESET":"); break; default: - ShowError("In function _ShowMessage() -> Invalid flag passed.\n"); + printf("In function _ShowMessage() -> Invalid flag passed.\n"); return 1; } - output = (char*)malloc(sizeof(char)*(strlen(prefix)+strlen(string))+1); - if (output == NULL) { - return 1; -// abort(); // Kill server? + + if (!(flag == MSG_DEBUG && !SHOW_DEBUG_MSG)) { + if (flag != MSG_NONE) + printf ("%s ", prefix); + vprintf (string, ap); + fflush (stdout); } - strcpy(output,prefix); - strcat(output,string); - printf(output); - fflush(stdout); + + 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) { - printf("\033[1;31m[Error]\033[0;0m: Could not open \033[1;29m%s\033[0;0m, file not found.\n",OUTPUT_MESSAGES_LOG); + printf(CL_RED"[Error]"CL_RESET": Could not open '"CL_WHITE"%s"CL_RESET"', file not found.\n",OUTPUT_MESSAGES_LOG); fflush(stdout); return; } @@ -71,3 +74,67 @@ int _ShowMessage(const char *string, enum msg_type flag){ // by MC Cameri */ return 0; } + +int _ShowMessage(enum msg_type flag, const char *string, ...) +{ + va_list ap; + + va_start(ap, string); + return _vShowMessage(flag, string, ap); +} + +// direct printf replacement +int ShowMessage(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_NONE, string, ap); +} +int ShowStatus(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_STATUS, string, ap); +} +int ShowSQL(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_SQL, string, ap); +} +int ShowInfo(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_INFORMATION, string, ap); +} +int ShowNotice(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_NOTICE, string, ap); +} +int ShowWarning(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_WARNING, string, ap); +} +int ShowDebug(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_DEBUG, string, ap); +} +int ShowError(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_ERROR, string, ap); +} +int ShowFatalError(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_FATALERROR, string, ap); +} diff --git a/src/common/showmsg.h b/src/common/showmsg.h index 1c4a2dfcb..b5f4d4bfd 100644 --- a/src/common/showmsg.h +++ b/src/common/showmsg.h @@ -1,50 +1,57 @@ #ifndef _SHOWMSG_H_ #define _SHOWMSG_H_ -extern char tmp_output[1024]; - -enum msg_type {MSG_STATUS,/* MSG_SQL, */MSG_INFORMATION,MSG_NOTICE,MSG_WARNING,MSG_ERROR,MSG_FATALERROR}; - -extern int _ShowMessage(const char *string, enum msg_type flag); - -/* MSG_XX */ - #define ShowMsg(string,flag) _ShowMessage(string,flag) -// #define DisplayMsg(string,flag) _ShowMessage(string,flag) - #define ShowMessage(string,flag) _ShowMessage(string,flag) - -/* MSG_STATUS */ - #define ShowStatus(string) _ShowMessage(string,MSG_STATUS) -// #define DisplayStatus(string) _ShowMessage(string,MSG_STATUS) - -/* MSG_SQL*/ -// #define ShowSQL(string) _ShowMessage(string,MSG_SQL) -// #define DisplaySQL(string) _ShowMessage(string,MSG_SQL) - -/* MSG_INFORMATION */ - #define ShowInfo(string) _ShowMessage(string,MSG_INFORMATION) -// #define DisplayInfo(string) _ShowMessage(string,MSG_INFORMATION) -// #define ShowInformation(string) _ShowMessage(string,MSG_INFORMATION) -// #define DisplayInformation(string) _ShowMessage(string,MSG_INFORMATION) - -/* MSG_NOTICE */ - #define ShowNotice(string) _ShowMessage(string,MSG_NOTICE) -// #define DisplayNotice(string) _ShowMessage(string,MSG_NOTICE) - -/* */ - #define ShowWarning(string) _ShowMessage(string,MSG_WARNING) -// #define DisplayWarning(string) _ShowMessage(string,MSG_WARNING) -// #define Warn(string) _ShowMessage(string,MSG_WARNING) +//davidsiaw, 'lookee' here! +#define SHOW_DEBUG_MSG 1 + +#ifdef _WIN32 +#define CL_RESET "" +#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 "" +#else +#define CL_RESET "\033[0;0m" +#define CL_NORMAL CL_RESET +#define CL_NONE CL_RESET +#define CL_WHITE "\033[1;29m" +#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" +#endif -/* MSG_ERROR */ - #define ShowError(string) _ShowMessage(string,MSG_ERROR) -// #define DisplayError(string) _ShowMessage(string,MSG_ERROR) -// #define OutputError(string) _ShowMessage(string,MSG_ERROR) +extern char tmp_output[1024]; -/* MSG_FATALERROR */ - #define ShowFatalError(string) _ShowMessage(string,MSG_FATALERROR) -// #define DisplayFatalError(string) _ShowMessage(string,MSG_ERROR) -// #define Terminate(string) _ShowMessage(string,MSG_FATALERROR) -// #define Kill(string) _ShowMessage(string,MSG_FATALERROR) -// #define AbortEx(string) _ShowMessage(string,MSG_FATALERROR) +enum msg_type { + MSG_NONE, + MSG_STATUS, + MSG_SQL, + MSG_INFORMATION, + MSG_NOTICE, + MSG_WARNING, + MSG_DEBUG, + MSG_ERROR, + MSG_FATALERROR +}; + +extern int ShowMessage(const char *, ...); +extern int ShowStatus(const char *, ...); +extern int ShowSQL(const char *, ...); +extern int ShowInfo(const char *, ...); +extern int ShowNotice(const char *, ...); +extern int ShowWarning(const char *, ...); +extern int ShowDebug(const char *, ...); +extern int ShowError(const char *, ...); +extern int ShowFatalError(const char *, ...); #endif diff --git a/src/common/socket.c b/src/common/socket.c index 4afcf50d4..64f660a11 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -3,11 +3,14 @@ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> +#include <errno.h> #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winsock2.h> +#include <io.h> +typedef int socklen_t; #else #include <sys/socket.h> #include <netinet/in.h> @@ -16,14 +19,21 @@ #include <sys/time.h> #include <unistd.h> #include <sys/ioctl.h> + +#ifndef SIOCGIFCONF +#include <sys/sockio.h> // SIOCGIFCONF on Solaris, maybe others? [Shinomori] +#endif + #endif #include <fcntl.h> #include <string.h> -#include "mmo.h" // [Valaris] thanks to fov #include "socket.h" -#include "utils.h" +#include "../common/dll.h" +#include "../common/mmo.h" // [Valaris] thanks to fov +#include "../common/timer.h" +#include "../common/utils.h" #ifdef MEMWATCH #include "memwatch.h" @@ -31,6 +41,27 @@ fd_set readfds; int fd_max; +time_t tick_; +time_t stall_time_ = 60; +int ip_rules = 1; + +// #define UPNP + +#ifdef UPNP +#if defined(CYGWIN) || defined(_WIN32) +DLL upnp_dll; +int (*upnp_init)(); +int (*upnp_final)(); +int (*firewall_addport)(char *desc, int port); +int (*upnp_addport)(char *desc, char *ip, int port); +extern char *argp; + +int release_mappings = 1; +int close_ports = 1; +#else +#error This doesnt work with non-Windows yet +#endif +#endif int rfifo_size = 65536; int wfifo_size = 65536; @@ -39,6 +70,8 @@ int wfifo_size = 65536; #define TCP_FRAME_LEN 1053 #endif +#define CONVIP(ip) ip&0xFF,(ip>>8)&0xFF,(ip>>16)&0xFF,ip>>24 + struct socket_data *session[FD_SETSIZE]; static int null_parse(int fd); @@ -46,6 +79,7 @@ static int (*default_func_parse)(int) = null_parse; static int null_console_parse(char *buf); static int (*default_console_parse)(char*) = null_console_parse; +static int connect_check(unsigned int ip); /*====================================== * CORE : Set function @@ -56,7 +90,10 @@ void set_defaultparse(int (*defaultparse)(int)) default_func_parse = defaultparse; } -#ifdef NSOCKET +void set_nonblocking(int fd, int yes) { + setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes); +} + static void setsocketopts(int fd) { int yes = 1; // reuse fix @@ -65,13 +102,12 @@ static void setsocketopts(int fd) #ifdef SO_REUSEPORT setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes); #endif - setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes); + set_nonblocking(fd, yes); setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &wfifo_size , sizeof(rfifo_size )); setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &rfifo_size , sizeof(rfifo_size )); } -#endif /* NSOCKET */ /*====================================== * CORE : Socket Sub Function *-------------------------------------- @@ -98,19 +134,10 @@ static int recv_to_fifo(int fd) //{ int i; printf("recv %d : ",fd); for(i=0;i<len;i++){ printf("%02x ",RFIFOB(fd,session[fd]->rdata_size+i)); } printf("\n");} if(len>0){ session[fd]->rdata_size+=len; + session[fd]->rdata_tick = tick_; } else if(len<=0){ // value of connection is not necessary the same -// if (fd == 4) // Removed [Yor] -// printf("Char-Server Has Disconnected.\n"); -// else if (fd == 5) // Removed [Yor] -// printf("Attempt To Log In Successful.\n"); -// else if (fd == 7) // Removed [Yor] -// printf("Char-Server Has Disconnected.\n"); -// else if (fd == 8) // Removed [Valaris] -// printf("%s has logged off your server.\n",RFIFOP(fd,6)); // Removed [Valaris] - -// else if (fd != 8) // [Valaris] - printf("set eof : connection #%d\n", fd); +// printf("set eof : connection #%d\n", fd); session[fd]->eof=1; } return 0; @@ -121,8 +148,10 @@ static int send_from_fifo(int fd) int len; //printf("send_from_fifo : %d\n",fd); - if(session[fd]->eof) + if(session[fd]->eof || session[fd]->wdata == 0) return -1; + if (session[fd]->wdata_size == 0) + return 0; #ifdef _WIN32 len=send(fd, session[fd]->wdata,session[fd]->wdata_size, 0); @@ -141,13 +170,22 @@ static int send_from_fifo(int fd) } else { session[fd]->wdata_size=0; } - } else { - printf("set eof :%d\n",fd); + } else if (errno != EAGAIN) { +// printf("set eof :%d\n",fd); session[fd]->eof=1; } return 0; } +void flush_fifos() +{ + int i; + for(i=0;i<fd_max;i++) + if(session[i] != NULL && + session[i]->func_send == send_from_fifo) + send_from_fifo(i); +} + static int null_parse(int fd) { printf("null_parse : %d\n",fd); @@ -165,45 +203,40 @@ static int connect_client(int listen_fd) int fd; struct sockaddr_in client_address; int len; +#ifndef _WIN32 int result; -#ifndef NSOCKET - int yes = 1; // reuse fix -#endif /* not NSOCKET */ +#endif //printf("connect_client : %d\n",listen_fd); len=sizeof(client_address); - fd=accept(listen_fd,(struct sockaddr*)&client_address,&len); + fd = accept(listen_fd,(struct sockaddr*)&client_address,(socklen_t*)&len); if(fd_max<=fd) fd_max=fd+1; -#ifndef NSOCKET - setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes); -#ifdef SO_REUSEPORT - setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes); -#endif - setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes); -#else /* NSOCKET */ setsocketopts(fd); -#endif /* NSOCKET */ - if(fd==-1) + if(fd==-1) { perror("accept"); - else + return -1; + } else if (ip_rules && !connect_check(*(unsigned int*)(&client_address.sin_addr))) { + close(fd); + return -1; + } else FD_SET(fd,&readfds); #ifdef _WIN32 - { - unsigned long val = 1; - ioctlsocket(fd, FIONBIO, &val); - } + { + unsigned long val = 1; + ioctlsocket(fd, FIONBIO, &val); + } #else result = fcntl(fd, F_SETFL, O_NONBLOCK); #endif CREATE(session[fd], struct socket_data, 1); - CREATE(session[fd]->rdata, char, rfifo_size); - CREATE(session[fd]->wdata, char, wfifo_size); + CREATE_A(session[fd]->rdata, unsigned char, rfifo_size); + CREATE_A(session[fd]->wdata, unsigned char, wfifo_size); session[fd]->max_rdata = rfifo_size; session[fd]->max_wdata = wfifo_size; @@ -211,6 +244,7 @@ static int connect_client(int listen_fd) session[fd]->func_send = send_from_fifo; session[fd]->func_parse = default_func_parse; session[fd]->client_addr = client_address; + session[fd]->rdata_tick = tick_; //printf("new_session : %d %d\n",fd,session[fd]->eof); return fd; @@ -221,9 +255,6 @@ int make_listen_port(int port) struct sockaddr_in server_address; int fd; int result; -#ifndef NSOCKET - int yes = 1; // reuse fix -#endif /* not NSOCKET */ fd = socket( AF_INET, SOCK_STREAM, 0 ); if(fd_max<=fd) fd_max=fd+1; @@ -237,19 +268,11 @@ int make_listen_port(int port) result = fcntl(fd, F_SETFL, O_NONBLOCK); #endif -#ifndef NSOCKET - setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes); -#ifdef SO_REUSEPORT - setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes); -#endif - setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes); -#else /* NSOCKET */ setsocketopts(fd); -#endif /* NSOCKET */ server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = htonl( INADDR_ANY ); - server_address.sin_port = htons(port); + server_address.sin_port = htons((unsigned short)port); result = bind(fd, (struct sockaddr*)&server_address, sizeof(server_address)); if( result == -1 ) { @@ -276,16 +299,83 @@ int make_listen_port(int port) return fd; } +int make_listen_bind(long ip,int port) +{ + struct sockaddr_in server_address; + int fd; + int result; + + fd = socket( AF_INET, SOCK_STREAM, 0 ); + if(fd_max<=fd) fd_max=fd+1; + +#ifdef _WIN32 + { + unsigned long val = 1; + ioctlsocket(fd, FIONBIO, &val); + } +#else + result = fcntl(fd, F_SETFL, O_NONBLOCK); +#endif + + setsocketopts(fd); + + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = ip; + server_address.sin_port = htons((unsigned short)port); + +#ifdef UPNP + if (upnp_dll) { + int localaddr = ntohl(addr_[0]); + unsigned char *natip = (unsigned char *)&localaddr; + char buf[16]; + sprintf(buf, "%d.%d.%d.%d", natip[0], natip[1], natip[2], natip[3]); + //printf("natip=%d.%d.%d.%d\n", natip[0], natip[1], natip[2], natip[3]); + if (firewall_addport(argp, port)) + printf ("Firewall port %d successfully opened\n", port); + if (natip[0] == 192 && natip[1] == 168) { + if (upnp_addport(argp, natip, port)) + printf ("Upnp mappings successfull\n"); + else printf ("Upnp mapping failed\n"); + } + } +#endif + + result = bind(fd, (struct sockaddr*)&server_address, sizeof(server_address)); + if( result == -1 ) { + perror("bind"); + exit(1); + } + result = listen( fd, 5 ); + if( result == -1 ) { /* error */ + perror("listen"); + exit(1); + } + + FD_SET(fd, &readfds ); + + CREATE(session[fd], struct socket_data, 1); + + if(session[fd]==NULL){ + printf("out of memory : make_listen_bind\n"); + exit(1); + } + memset(session[fd],0,sizeof(*session[fd])); + session[fd]->func_recv = connect_client; + + return fd; +} + // Console Reciever [Wizputer] int console_recieve(int i) { int n; char *buf; - - CREATE(buf, char , 64); - + + CREATE_A(buf, char , 64); + memset(buf,0,sizeof(64)); n = read(0, buf , 64); + if ( n < 0 ) printf("Console input read error\n"); else @@ -307,48 +397,36 @@ static int null_console_parse(char *buf) // Console Input [Wizputer] int start_console(void) { FD_SET(0,&readfds); - + CREATE(session[0], struct socket_data, 1); if(session[0]==NULL){ printf("out of memory : start_console\n"); exit(1); } - + memset(session[0],0,sizeof(*session[0])); - + session[0]->func_recv = console_recieve; session[0]->func_console = default_console_parse; - + return 0; -} - +} + int make_connection(long ip,int port) { struct sockaddr_in server_address; int fd; int result; -#ifndef NSOCKET - int yes = 1; // reuse fix -#endif /* not NSOCKET */ fd = socket( AF_INET, SOCK_STREAM, 0 ); -#ifndef NSOCKET - if(fd_max<=fd) fd_max=fd+1; - setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes); -#ifdef SO_REUSEPORT - setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes); -#endif - setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes); -#else /* NSOCKET */ - if(fd_max<=fd) + if(fd_max<=fd) fd_max=fd+1; setsocketopts(fd); -#endif /* NSOCKET */ server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = ip; - server_address.sin_port = htons(port); + server_address.sin_port = htons((unsigned short)port); #ifdef _WIN32 { @@ -364,31 +442,32 @@ int make_connection(long ip,int port) FD_SET(fd,&readfds); CREATE(session[fd], struct socket_data, 1); - CREATE(session[fd]->rdata, char, rfifo_size); - CREATE(session[fd]->wdata, char, wfifo_size); + CREATE_A(session[fd]->rdata, unsigned char, rfifo_size); + CREATE_A(session[fd]->wdata, unsigned char, wfifo_size); session[fd]->max_rdata = rfifo_size; session[fd]->max_wdata = wfifo_size; session[fd]->func_recv = recv_to_fifo; session[fd]->func_send = send_from_fifo; session[fd]->func_parse = default_func_parse; + session[fd]->rdata_tick = tick_; return fd; } int delete_session(int fd) { - if(fd<0 || fd>=FD_SETSIZE) + if(fd<=0 || fd>=FD_SETSIZE) return -1; FD_CLR(fd,&readfds); if(session[fd]){ if(session[fd]->rdata) - free(session[fd]->rdata); + aFree(session[fd]->rdata); if(session[fd]->wdata) - free(session[fd]->wdata); + aFree(session[fd]->wdata); if(session[fd]->session_data) - free(session[fd]->session_data); - free(session[fd]); + aFree(session[fd]->session_data); + aFree(session[fd]); } session[fd]=NULL; //printf("delete_session:%d\n",fd); @@ -397,13 +476,16 @@ int delete_session(int fd) int realloc_fifo(int fd,int rfifo_size,int wfifo_size) { - struct socket_data *s=session[fd]; + struct socket_data *s; + + if (fd <= 0) return 0; + s = session[fd]; if( s->max_rdata != rfifo_size && s->rdata_size < rfifo_size){ - RECREATE(s->rdata, char, rfifo_size); + RECREATE(s->rdata, unsigned char, rfifo_size); s->max_rdata = rfifo_size; } if( s->max_wdata != wfifo_size && s->wdata_size < wfifo_size){ - RECREATE(s->wdata, char, wfifo_size); + RECREATE(s->wdata, unsigned char, wfifo_size); s->max_wdata = wfifo_size; } return 0; @@ -411,11 +493,12 @@ int realloc_fifo(int fd,int rfifo_size,int wfifo_size) int WFIFOSET(int fd,int len) { - struct socket_data *s=session[fd]; -#ifdef NSOCKET + struct socket_data *s; + + if (fd <= 0) return 0; + s = session[fd]; if (s == NULL || s->wdata == NULL) return 0; -#endif /* NSOCKET */ if( s->wdata_size+len+16384 > s->max_wdata ){ unsigned char *sin_addr = (unsigned char *)&s->client_addr.sin_addr; realloc_fifo(fd,s->max_rdata, s->max_wdata <<1 ); @@ -423,10 +506,8 @@ int WFIFOSET(int fd,int len) } s->wdata_size=(s->wdata_size+(len)+2048 < s->max_wdata) ? s->wdata_size+len : (printf("socket: %d wdata lost !!\n",fd),s->wdata_size); -#ifdef NSOCKET - if (s->wdata_size > (TCP_FRAME_LEN)) + if (s->wdata_size > (TCP_FRAME_LEN)) send_from_fifo(fd); -#endif /* NSOCKET */ return 0; } @@ -436,7 +517,10 @@ int do_sendrecv(int next) struct timeval timeout; int ret,i; - rfd=readfds; + tick_ = time(0); + + memcpy(&rfd, &readfds, sizeof(rfd)); + FD_ZERO(&wfd); for(i=0;i<fd_max;i++){ if(!session[i] && FD_ISSET(i,&readfds)){ @@ -460,13 +544,11 @@ int do_sendrecv(int next) if(FD_ISSET(i,&wfd)){ //printf("write:%d\n",i); if(session[i]->func_send) - //send_from_fifo(i); session[i]->func_send(i); } if(FD_ISSET(i,&rfd)){ //printf("read:%d\n",i); if(session[i]->func_recv) - //recv_to_fifo(i); session[i]->func_recv(i); } } @@ -479,6 +561,8 @@ int do_parsepacket(void) for(i=0;i<fd_max;i++){ if(!session[i]) continue; + if ((session[i]->rdata_tick != 0) && ((tick_ - session[i]->rdata_tick) > stall_time_)) + session[i]->eof = 1; if(session[i]->rdata_size==0 && session[i]->eof==0) continue; if(session[i]->func_parse){ @@ -491,14 +575,306 @@ int do_parsepacket(void) return 0; } -void do_socket(void) +/* DDoS UŒ‚‘Îô */ + +enum { + ACO_DENY_ALLOW=0, + ACO_ALLOW_DENY, + ACO_MUTUAL_FAILTURE, +}; + +struct _access_control { + unsigned int ip; + unsigned int mask; +}; + +static struct _access_control *access_allow; +static struct _access_control *access_deny; +static int access_order=ACO_DENY_ALLOW; +static int access_allownum=0; +static int access_denynum=0; +static int access_debug=0; +static int ddos_count = 10; +static int ddos_interval = 3000; +static int ddos_autoreset = 600*1000; + +struct _connect_history { + struct _connect_history *next; + struct _connect_history *prev; + int status; + int count; + unsigned int ip; + unsigned int tick; +}; +static struct _connect_history *connect_history[0x10000]; +static int connect_check_(unsigned int ip); + +// Ú‘±‚Å‚«‚é‚©‚Ç‚¤‚©‚ÌŠm”F +// false : Ú‘±OK +// true : Ú‘±NG +static int connect_check(unsigned int ip) { + int result = connect_check_(ip); + if(access_debug) { + printf("connect_check: Connection from %d.%d.%d.%d %s\n", + CONVIP(ip),result ? "allowed." : "denied!"); + } + return result; +} + +static int connect_check_(unsigned int ip) { + struct _connect_history *hist = connect_history[ip & 0xFFFF]; + struct _connect_history *hist_new; + int i,is_allowip = 0,is_denyip = 0,connect_ok = 0; + + // allow , deny ƒŠƒXƒg‚É“ü‚Á‚Ä‚¢‚é‚©Šm”F + for(i = 0;i < access_allownum; i++) { + if((ip & access_allow[i].mask) == (access_allow[i].ip & access_allow[i].mask)) { + if(access_debug) { + printf("connect_check: Found match from allow list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n", + CONVIP(ip), + CONVIP(access_allow[i].ip), + CONVIP(access_allow[i].mask)); + } + is_allowip = 1; + break; + } + } + for(i = 0;i < access_denynum; i++) { + if((ip & access_deny[i].mask) == (access_deny[i].ip & access_deny[i].mask)) { + if(access_debug) { + printf("connect_check: Found match from deny list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n", + CONVIP(ip), + CONVIP(access_deny[i].ip), + CONVIP(access_deny[i].mask)); + } + is_denyip = 1; + break; + } + } + // ƒRƒlƒNƒgo—ˆ‚é‚©‚Ç‚¤‚©Šm”F + // connect_ok + // 0 : –³ðŒ‚É‹‘”Û + // 1 : “c‘ã–Cƒ`ƒFƒbƒN‚ÌŒ‹‰ÊŽŸ‘æ + // 2 : –³ðŒ‚É‹–‰Â + switch(access_order) { + case ACO_DENY_ALLOW: + default: + if(is_allowip) { + connect_ok = 2; + } else if(is_denyip) { + connect_ok = 0; + } else { + connect_ok = 1; + } + break; + case ACO_ALLOW_DENY: + if(is_denyip) { + connect_ok = 0; + } else if(is_allowip) { + connect_ok = 2; + } else { + connect_ok = 1; + } + break; + case ACO_MUTUAL_FAILTURE: + if(is_allowip) { + connect_ok = 2; + } else { + connect_ok = 0; + } + break; + } + + // Ú‘±—š—ð‚𒲂ׂé + while(hist) { + if(ip == hist->ip) { + // “¯‚¶IP”Œ© + if(hist->status) { + // ban ƒtƒ‰ƒO‚ª—§‚Á‚Ä‚é + return (connect_ok == 2 ? 1 : 0); + } else if(DIFF_TICK(gettick(),hist->tick) < ddos_interval) { + // ddos_interval•bˆÈ“à‚ÉƒŠƒNƒGƒXƒg—L‚è + hist->tick = gettick(); + if(hist->count++ >= ddos_count) { + // ddos UŒ‚‚ðŒŸo + hist->status = 1; + printf("connect_check: DDOS Attack detected from %d.%d.%d.%d!\n", + CONVIP(ip)); + return (connect_ok == 2 ? 1 : 0); + } else { + return connect_ok; + } + } else { + // ddos_interval•bˆÈ“à‚ÉƒŠƒNƒGƒXƒg–³‚¢‚̂Ń^ƒCƒ}[ƒNƒŠƒA + hist->tick = gettick(); + hist->count = 0; + return connect_ok; + } + } + hist = hist->next; + } + // IPƒŠƒXƒg‚É–³‚¢‚Ì‚ÅV‹Kì¬ + hist_new = (struct _connect_history *) aCalloc(1,sizeof(struct _connect_history)); + hist_new->ip = ip; + hist_new->tick = gettick(); + if(connect_history[ip & 0xFFFF] != NULL) { + hist = connect_history[ip & 0xFFFF]; + hist->prev = hist_new; + hist_new->next = hist; + } + connect_history[ip & 0xFFFF] = hist_new; + return connect_ok; +} + +static int connect_check_clear(int tid,unsigned int tick,int id,int data) { + int i; + int clear = 0; + int list = 0; + struct _connect_history *hist , *hist2; + for(i = 0;i < 0x10000 ; i++) { + hist = connect_history[i]; + while(hist) { + if( + (DIFF_TICK(tick,hist->tick) > ddos_interval * 3 && !hist->status) || + (DIFF_TICK(tick,hist->tick) > ddos_autoreset && hist->status) + ) { + // clear data + hist2 = hist->next; + if(hist->prev) { + hist->prev->next = hist->next; + } else { + connect_history[i] = hist->next; + } + if(hist->next) { + hist->next->prev = hist->prev; + } + aFree(hist); + hist = hist2; + clear++; + } else { + hist = hist->next; + list++; + } + } + } + if(access_debug) { + printf("connect_check_clear: Cleared %d of %d from IP list.\n", clear, clear+list); + } + return list; +} + +// IPƒ}ƒXƒNƒ`ƒFƒbƒN +int access_ipmask(const char *str,struct _access_control* acc) { - FD_ZERO(&readfds); + unsigned int mask=0,i=0,m,ip, a0,a1,a2,a3; + if( !strcmp(str,"all") ) { + ip = 0; + mask = 0; + } else { + if( sscanf(str,"%d.%d.%d.%d%n",&a0,&a1,&a2,&a3,&i)!=4 || i==0) { + printf("access_ipmask: Unknown format %s!\n",str); + return 0; + } + ip = (a3 << 24) | (a2 << 16) | (a1 << 8) | a0; + + if(sscanf(str+i,"/%d.%d.%d.%d",&a0,&a1,&a2,&a3)==4 ){ + mask = (a3 << 24) | (a2 << 16) | (a1 << 8) | a0; + } else if(sscanf(str+i,"/%d",&m) == 1) { + for(i=0;i<m;i++) { + mask = (mask >> 1) | 0x80000000; + } + mask = ntohl(mask); + } else { + mask = 0xFFFFFFFF; + } + } + if(access_debug) { + printf("access_ipmask: Loaded IP:%d.%d.%d.%d mask:%d.%d.%d.%d\n", + CONVIP(ip), CONVIP(mask)); + } + acc->ip = ip; + acc->mask = mask; + return 1; +} + +int socket_config_read(const char *cfgName) { + int i; + char line[1024],w1[1024],w2[1024]; + FILE *fp; + + fp=fopen(cfgName, "r"); + if(fp==NULL){ + printf("File not found: %s\n", cfgName); + return 1; + } + while(fgets(line,1020,fp)){ + if(line[0] == '/' && line[1] == '/') + continue; + i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2); + if(i!=2) + continue; + if(strcmpi(w1,"stall_time")==0){ + stall_time_ = atoi(w2); + } else if(strcmpi(w1,"enable_ip_rules")==0){ + if(strcmpi(w2,"yes")==0) + ip_rules = 1; + else if(strcmpi(w2,"no")==0) + ip_rules = 0; + else ip_rules = atoi(w2); + } else if(strcmpi(w1,"order")==0){ + access_order=atoi(w2); + if(strcmpi(w2,"deny,allow")==0) access_order=ACO_DENY_ALLOW; + if(strcmpi(w2,"allow,deny")==0) access_order=ACO_ALLOW_DENY; + if(strcmpi(w2,"mutual-failure")==0) access_order=ACO_MUTUAL_FAILTURE; + } else if(strcmpi(w1,"allow")==0){ + access_allow = (struct _access_control *) aRealloc(access_allow,(access_allownum+1)*sizeof(struct _access_control)); + if(access_ipmask(w2,&access_allow[access_allownum])) { + access_allownum++; + } + } else if(strcmpi(w1,"deny")==0){ + access_deny = (struct _access_control *) aRealloc(access_deny,(access_denynum+1)*sizeof(struct _access_control)); + if(access_ipmask(w2,&access_deny[access_denynum])) { + access_denynum++; + } + } else if(!strcmpi(w1,"ddos_interval")){ + ddos_interval = atoi(w2); + } else if(!strcmpi(w1,"ddos_count")){ + ddos_count = atoi(w2); + } else if(!strcmpi(w1,"ddos_autoreset")){ + ddos_autoreset = atoi(w2); + } else if(!strcmpi(w1,"debug")){ + if(strcmpi(w2,"yes")==0) + access_debug = 1; + else if(strcmpi(w2,"no")==0) + access_debug = 0; + else access_debug = atoi(w2); + #ifdef UPNP + } else if(!strcmpi(w1,"release_mappings")){ + if(strcmpi(w2,"yes")==0) + release_mappings = 1; + else if(strcmpi(w2,"no")==0) + release_mappings = 0; + else release_mappings = atoi(w2); + } else if(!strcmpi(w1,"close_ports")){ + if(strcmpi(w2,"yes")==0) + close_ports = 1; + else if(strcmpi(w2,"no")==0) + close_ports = 0; + else close_ports = atoi(w2); + #endif + } else if (strcmpi(w1, "import") == 0) + socket_config_read(w2); + } + fclose(fp); + return 0; } int RFIFOSKIP(int fd,int len) { - struct socket_data *s=session[fd]; + struct socket_data *s; + + if (fd <= 0) return 0; + s = session[fd]; if (s->rdata_size-s->rdata_pos-len<0) { fprintf(stderr,"too many skip\n"); @@ -521,7 +897,7 @@ int Net_Init(void) unsigned int i; char fullhost[255]; struct hostent* hent; - + /* Start up the windows networking */ WSADATA wsaData; @@ -533,7 +909,7 @@ int Net_Init(void) if(gethostname(fullhost, sizeof(fullhost)) == SOCKET_ERROR) { printf("Ugg.. no hostname defined!\n"); return 0; - } + } // XXX This should look up the local IP addresses in the registry // instead of calling gethostbyname. However, the way IP addresses @@ -566,7 +942,7 @@ int Net_Init(void) return 0; } - for(pos = 0; pos < ic.ifc_len;) + for(pos = 0; pos < ic.ifc_len;) { struct ifreq * ir = (struct ifreq *) (ic.ifc_buf + pos); @@ -593,3 +969,101 @@ int Net_Init(void) return(0); } + +#ifdef UPNP +// not implemented yet ^^; +void do_init_upnp(void) +{ + int *_release_mappings; + int *_close_ports; + + upnp_dll = DLL_OPEN ("upnp.dll"); + if (!upnp_dll) { + printf ("Cannot open upnp.dll: %s\n", dlerror()); + return; + } + DLL_SYM (upnp_init, upnp_dll, "do_init"); + DLL_SYM (upnp_final, upnp_dll, "do_final"); + DLL_SYM (firewall_addport, upnp_dll, "Firewall_AddPort"); + DLL_SYM (upnp_addport, upnp_dll, "UPNP_AddPort"); + if (!upnp_init || !upnp_final || !firewall_addport || !upnp_addport) { + printf ("Cannot load symbol: %s\n", dlerror()); + DLL_CLOSE (upnp_dll); + upnp_dll = NULL; + return; + } + + DLL_SYM (_release_mappings, upnp_dll, "release_mappings"); + DLL_SYM (_close_ports, upnp_dll, "close_ports"); + if (release_mappings && _release_mappings) + *_release_mappings = release_mappings; + if (close_ports && _close_ports) + *_close_ports = close_ports; + + if (upnp_init() == 0) { + printf ("Error initialising upnp.dll, unloading...\n"); + DLL_CLOSE (upnp_dll); + upnp_dll = NULL; + } + return; +} +#endif + +void do_final_socket(void) +{ + int i; + struct _connect_history *hist , *hist2; + for(i=0; i<fd_max; i++) { + if(session[i]) { + delete_session(i); + } + } + for(i=0; i<0x10000; i++) { + hist = connect_history[i]; + while(hist) { + hist2 = hist->next; + aFree(hist); + hist = hist2; + } + } + if (access_allow) + aFree(access_allow); + if (access_deny) + aFree(access_deny); + + // session[0] ‚̃_ƒ~[ƒf[ƒ^‚ðíœ + aFree(session[0]->rdata); + aFree(session[0]->wdata); + aFree(session[0]); + +#ifdef UPNP + if (upnp_dll) { + upnp_final(); + DLL_CLOSE(upnp_dll); + } +#endif +} + +void do_socket(void) +{ + char *SOCKET_CONF_FILENAME = "conf/packet_athena.conf"; + + FD_ZERO(&readfds); + + atexit(do_final_socket); + socket_config_read(SOCKET_CONF_FILENAME); + + // session[0] ‚Ƀ_ƒ~[ƒf[ƒ^‚ðŠm•Û‚·‚é + CREATE(session[0], struct socket_data, 1); + CREATE_A(session[0]->rdata, unsigned char, rfifo_size); + CREATE_A(session[0]->wdata, unsigned char, wfifo_size); + session[0]->max_rdata = rfifo_size; + session[0]->max_wdata = wfifo_size; + + // ‚Æ‚è‚ ‚¦‚¸‚T•ª‚²‚Ƃɕs—v‚ȃf[ƒ^‚ð휂·‚é + add_timer_interval(gettick()+1000,connect_check_clear,0,0,300*1000); + +#ifdef UPNP + do_init_upnp(); +#endif +} diff --git a/src/common/socket.h b/src/common/socket.h index e3ad0826a..37d41203e 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -5,24 +5,31 @@ #include <stdio.h> -#ifdef _WIN32 +#ifdef __WIN32 #include <winsock.h> #else #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #endif +#include <time.h> +#include "malloc.h" + +extern time_t tick_; +extern time_t stall_time_; // define declaration +#define RFIFOSPACE(fd) (session[fd]->max_rdata-session[fd]->rdata_size) #define RFIFOP(fd,pos) (session[fd]->rdata+session[fd]->rdata_pos+(pos)) -#define RFIFOB(fd,pos) (*(unsigned char*)(session[fd]->rdata+session[fd]->rdata_pos+(pos))) -#define RFIFOW(fd,pos) (*(unsigned short*)(session[fd]->rdata+session[fd]->rdata_pos+(pos))) -#define RFIFOL(fd,pos) (*(unsigned int*)(session[fd]->rdata+session[fd]->rdata_pos+(pos))) -//#define RFIFOSKIP(fd,len) ((session[fd]->rdata_size-session[fd]->rdata_pos-(len)<0) ? (fprintf(stderr,"too many skip\n"),exit(1)) : (session[fd]->rdata_pos+=(len))) -#define RFIFOREST(fd) (session[fd]->rdata_size-session[fd]->rdata_pos) +// use function instead of macro. +#define RFIFOB(fd,pos) (*(unsigned char*)RFIFOP(fd,pos)) +#define RFIFOW(fd,pos) (*(unsigned short*)RFIFOP(fd,pos)) +#define RFIFOL(fd,pos) (*(unsigned int*)RFIFOP(fd,pos)) +#define RFIFOREST(fd) (session[fd]->rdata_size-session[fd]->rdata_pos) #define RFIFOFLUSH(fd) (memmove(session[fd]->rdata,RFIFOP(fd,0),RFIFOREST(fd)),session[fd]->rdata_size=RFIFOREST(fd),session[fd]->rdata_pos=0) -#define RFIFOSPACE(fd) (session[fd]->max_rdata-session[fd]->rdata_size) +//#define RFIFOSKIP(fd,len) ((session[fd]->rdata_size-session[fd]->rdata_pos-(len)<0) ? (fprintf(stderr,"too many skip\n"),exit(1)) : (session[fd]->rdata_pos+=(len))) + #define RBUFP(p,pos) (((unsigned char*)(p))+(pos)) #define RBUFB(p,pos) (*(unsigned char*)RBUFP((p),(pos))) #define RBUFW(p,pos) (*(unsigned short*)RBUFP((p),(pos))) @@ -30,9 +37,9 @@ #define WFIFOSPACE(fd) (session[fd]->max_wdata-session[fd]->wdata_size) #define WFIFOP(fd,pos) (session[fd]->wdata+session[fd]->wdata_size+(pos)) -#define WFIFOB(fd,pos) (*(unsigned char*)(session[fd]->wdata+session[fd]->wdata_size+(pos))) -#define WFIFOW(fd,pos) (*(unsigned short*)(session[fd]->wdata+session[fd]->wdata_size+(pos))) -#define WFIFOL(fd,pos) (*(unsigned int*)(session[fd]->wdata+session[fd]->wdata_size+(pos))) +#define WFIFOB(fd,pos) (*(unsigned char*)WFIFOP(fd,pos)) +#define WFIFOW(fd,pos) (*(unsigned short*)WFIFOP(fd,pos)) +#define WFIFOL(fd,pos) (*(unsigned int*)WFIFOP(fd,pos)) // use function instead of macro. //#define WFIFOSET(fd,len) (session[fd]->wdata_size = (session[fd]->wdata_size+(len)+2048 < session[fd]->max_wdata) ? session[fd]->wdata_size+len : session[fd]->wdata_size) #define WBUFP(p,pos) (((unsigned char*)(p))+(pos)) @@ -54,6 +61,7 @@ struct socket_data{ unsigned char *rdata,*wdata; int max_rdata,max_wdata; int rdata_size,wdata_size; + time_t rdata_tick; int rdata_pos; struct sockaddr_in client_addr; int (*func_recv)(int); @@ -80,6 +88,7 @@ extern int fd_max; // Function prototype declaration int make_listen_port(int); +int make_listen_bind(long,int); int make_connection(long,int); int delete_session(int); int realloc_fifo(int fd,int rfifo_size,int wfifo_size); @@ -90,6 +99,9 @@ int do_sendrecv(int next); int do_parsepacket(void); void do_socket(void); +extern void flush_fifos(); +extern void set_nonblocking(int fd, int yes); + int start_console(void); void set_defaultparse(int (*defaultparse)(int)); diff --git a/src/char_sql/strlib.c b/src/common/strlib.c index b113d96f5..2b130e76d 100644 --- a/src/char_sql/strlib.c +++ b/src/common/strlib.c @@ -4,18 +4,19 @@ #include "strlib.h" #include "utils.h" +#include "malloc.h" //----------------------------------------------- // string lib. -unsigned char* jstrescape (unsigned char* pt) { +char* jstrescape (char* pt) { //copy from here - unsigned char * ptr; + char *ptr; int i =0, j=0; - + //copy string to temporary - CREATE(ptr, char, J_MAX_MALLOC_SIZE); - strcpy (ptr,pt); - + CREATE_A(ptr, char, J_MAX_MALLOC_SIZE); + strcpy(ptr,pt); + while (ptr[i] != '\0') { switch (ptr[i]) { case '\'': @@ -31,14 +32,14 @@ unsigned char* jstrescape (unsigned char* pt) { } } pt[j++] = '\0'; - free (ptr); - return (unsigned char*) &pt[0]; + aFree (ptr); + return &pt[0]; } -unsigned char* jstrescapecpy (unsigned char* pt,unsigned char* spt) { +char* jstrescapecpy (char* pt,char* spt) { //copy from here int i =0, j=0; - + while (spt[i] != '\0') { switch (spt[i]) { case '\'': @@ -54,12 +55,12 @@ unsigned char* jstrescapecpy (unsigned char* pt,unsigned char* spt) { } } pt[j++] = '\0'; - return (unsigned char*) &pt[0]; + return &pt[0]; } -int jmemescapecpy (unsigned char* pt,unsigned char* spt, int size) { +int jmemescapecpy (char* pt,char* spt, int size) { //copy from here int i =0, j=0; - + while (i < size) { switch (spt[i]) { case '\'': @@ -77,3 +78,21 @@ int jmemescapecpy (unsigned char* pt,unsigned char* spt, int size) { // copy size is 0 ~ (j-1) return j; } + +//----------------------------------------------------- +// Function to suppress control characters in a string. +//----------------------------------------------------- +//int remove_control_chars(char *str) { +int remove_control_chars(unsigned char *str) { + int i; + int change = 0; + + for(i = 0; str[i]; i++) { + if (str[i] < 32) { + str[i] = '_'; + change = 1; + } + } + + return change; +} diff --git a/src/login_sql/strlib.h b/src/common/strlib.h index ddf29ab18..55920f823 100644 --- a/src/login_sql/strlib.h +++ b/src/common/strlib.h @@ -4,6 +4,10 @@ // String function library. // code by Jioh L. Jung (ziozzang@4wish.net) // This code is under license "BSD" -unsigned char* jstrescape (unsigned char* pt); -unsigned char* jstrescapecpy (unsigned char* pt,unsigned char* spt); +char* jstrescape (char* pt); +char* jstrescapecpy (char* pt,char* spt); +int jmemescapecpy (char* pt,char* spt, int size); + +// custom functions +int remove_control_chars(unsigned char *); #endif diff --git a/src/common/timer.c b/src/common/timer.c index 97c162e7f..6a740d47a 100644 --- a/src/common/timer.c +++ b/src/common/timer.c @@ -1,37 +1,34 @@ -// $Id: timer.c,v 1.1.1.1 2004/09/10 17:44:49 MagicalTux Exp $ +// $Id: timer.c,v 1.1.1.1 2004/09/10 17:44:49 Yor Exp $ // original : core.c 2003/02/26 18:03:12 Rev 1.7 +//#include <config.h> + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> -#ifdef _WIN32 -#include <winsock.h> +#ifdef __WIN32 +#define __USE_W32_SOCKETS +#include <windows.h> #else #include <sys/socket.h> #include <sys/time.h> #endif #include "timer.h" -#include "utils.h" +#include "malloc.h" #ifdef MEMWATCH #include "memwatch.h" #endif -// If the server shows no reaction when processing thousands of monsters - -// or connected by many clients, please increase TIMER_MIN_INTERVEL. - -#define TIMER_MIN_INTERVEL 50 - static struct TimerData* timer_data; -static int timer_data_max,timer_data_num; +static int timer_data_max, timer_data_num; static int* free_timer_list; static int free_timer_list_max, free_timer_list_pos; -static int timer_heap_max=0; //fixed Shinomori from eA forums +static int timer_heap_num = 0, timer_heap_max = 0; static int* timer_heap = NULL; // for debug @@ -42,38 +39,37 @@ struct timer_func_list { }; static struct timer_func_list* tfl_root; -#if defined(_WIN32) -void gettimeofday(struct timeval *t, struct timezone *dummy) -{ - DWORD millisec = GetTickCount(); +#ifdef __WIN32 +/* Modified struct timezone to void - we pass NULL anyway */ +void gettimeofday(struct timeval *t, void *dummy) { + DWORD millisec = GetTickCount(); - t->tv_sec = (int) (millisec / 1000); - t->tv_usec = (millisec % 1000) * 1000; + t->tv_sec = (int) (millisec / 1000); + t->tv_usec = (millisec % 1000) * 1000; } - #endif - // -int add_timer_func_list(int (*func)(int,unsigned int,int,int),char* name) -{ +int add_timer_func_list(int (*func)(int,unsigned int,int,int), char* name) { struct timer_func_list* tfl; - CREATE(tfl, struct timer_func_list, 1); - CREATE(tfl->name, char, strlen(name) + 1); + //CALLOC(tfl, struct timer_func_list, 1); + tfl = (struct timer_func_list*) aCalloc( sizeof(struct timer_func_list) , 1); + //MALLOC(tfl->name, char, strlen(name) + 1); + tfl->name = (char *) aMalloc( strlen(name) + 1 ); tfl->next = tfl_root; tfl->func = func; - strcpy(tfl->name,name); + strcpy(tfl->name, name); tfl_root = tfl; return 0; } -char* search_timer_func_list(int (*func)(int,unsigned int,int,int)) -{ +char* search_timer_func_list(int (*func)(int,unsigned int,int,int)) { struct timer_func_list* tfl; - for(tfl = tfl_root;tfl;tfl = tfl->next) { + + for(tfl = tfl_root; tfl; tfl = tfl->next) { if (func == tfl->func) return tfl->name; } @@ -85,19 +81,21 @@ char* search_timer_func_list(int (*func)(int,unsigned int,int,int)) *----------------------------*/ static unsigned int gettick_cache; static int gettick_count; -unsigned int gettick_nocache(void) -{ + +unsigned int gettick_nocache(void) { struct timeval tval; - gettimeofday(&tval,NULL); + + gettimeofday(&tval, NULL); gettick_count = 256; - return gettick_cache = tval.tv_sec * 1000 + tval.tv_usec/1000; + + return gettick_cache = tval.tv_sec * 1000 + tval.tv_usec / 1000; } -unsigned int gettick(void) -{ +unsigned int gettick(void) { gettick_count--; - if (gettick_count<0) + if (gettick_count < 0) return gettick_nocache(); + return gettick_cache; } @@ -105,71 +103,66 @@ unsigned int gettick(void) * CORE : Timer Heap *-------------------------------------- */ -static void push_timer_heap(int index) -{ - int i, h; - - if (timer_heap == NULL || timer_heap[0] + 1 >= timer_heap_max) { - int first = timer_heap == NULL; - - timer_heap_max += 256; - RECREATE(timer_heap, int, timer_heap_max); - memset(timer_heap + (timer_heap_max - 256), 0, sizeof(int) * 256); - if (first) - timer_heap[0] = 0; - } - - timer_heap[0]++; - - for (h = timer_heap[0]-1, i = (h - 1) / 2; - h > 0 && DIFF_TICK(timer_data[index].tick, - timer_data[timer_heap[i + 1]].tick) < 0; - i = (h - 1) / 2) { - timer_heap[h + 1] = timer_heap[i + 1]; - h = i; - } - timer_heap[h + 1] = index; -} - -static int top_timer_heap() -{ - if (timer_heap == NULL || timer_heap[0] <= 0) - return -1; - - return timer_heap[1]; -} - -static int pop_timer_heap() -{ - int i,h,k; - int ret,last; - - if (timer_heap == NULL || timer_heap[0] <= 0) - return -1; - ret = timer_heap[1]; - last = timer_heap[timer_heap[0]]; - timer_heap[0]--; - - for(h = 0,k = 2;k<timer_heap[0];k = k * 2 + 2) { - if (DIFF_TICK(timer_data[timer_heap[k + 1]].tick , timer_data[timer_heap[k]].tick)>0) - k--; - timer_heap[h + 1] = timer_heap[k + 1], h = k; +static void push_timer_heap(int index) { + int i, j; + int min, max, pivot; // for sorting + + // check number of element + if (timer_heap_num >= timer_heap_max) { + if (timer_heap_max == 0) { + timer_heap_max = 256; + //CALLOC(timer_heap, int, 256); + timer_heap = (int *) aCalloc( sizeof(int) , 256); + } else { + timer_heap_max += 256; + //REALLOC(timer_heap, int, timer_heap_max); + timer_heap = (int *) aRealloc( timer_heap, sizeof(int) * timer_heap_max); + memset(timer_heap + (timer_heap_max - 256), 0, sizeof(int) * 256); + } } - if (k == timer_heap[0]) - timer_heap[h + 1] = timer_heap[k], h = k-1; - for(i = (h-1)/2; - h>0 && DIFF_TICK(timer_data[timer_heap[i + 1]].tick , timer_data[last].tick)>0; - i = (h-1)/2) { - timer_heap[h + 1] = timer_heap[i + 1],h = i; + // do a sorting from higher to lower + j = timer_data[index].tick; // speed up + // with less than 4 values, it's speeder to use simple loop + if (timer_heap_num < 4) { + for(i = timer_heap_num; i > 0; i--) + if (j < timer_data[timer_heap[i - 1]].tick) + break; + else + timer_heap[i] = timer_heap[i - 1]; + timer_heap[i] = index; + // searching by dichotomie + } else { + // if lower actual item is higher than new + if (j < timer_data[timer_heap[timer_heap_num - 1]].tick) + timer_heap[timer_heap_num] = index; + else { + // searching position + min = 0; + max = timer_heap_num - 1; + while (min < max) { + pivot = (min + max) / 2; + if (j < timer_data[timer_heap[pivot]].tick) + min = pivot + 1; + else + max = pivot; + } + // move elements - do loop if there are a little number of elements to move + if (timer_heap_num - min < 5) { + for(i = timer_heap_num; i > min; i--) + timer_heap[i] = timer_heap[i - 1]; + // move elements - else use memmove (speeder for a lot of elements) + } else + memmove(&timer_heap[min + 1], &timer_heap[min], sizeof(int) * (timer_heap_num - min)); + // save new element + timer_heap[min] = index; + } } - timer_heap[h + 1] = last; - return ret; + timer_heap_num++; } -int add_timer(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int data) -{ +int add_timer(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int data) { struct TimerData* td; int i; @@ -180,24 +173,18 @@ int add_timer(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int } else i = timer_data_num; if (i >= timer_data_num) - for (i = timer_data_num;i<timer_data_max && timer_data[i].type; i++); + for (i = timer_data_num; i < timer_data_max && timer_data[i].type; i++); if (i >= timer_data_num && i >= timer_data_max) { - int j; if (timer_data_max == 0) { timer_data_max = 256; - CREATE(timer_data, struct TimerData, timer_data_max); + //CALLOC(timer_data, struct TimerData, timer_data_max); + timer_data = (struct TimerData*) aCalloc( sizeof(struct TimerData) , timer_data_max); } else { timer_data_max += 256; - RECREATE(timer_data, struct TimerData, timer_data_max); - if (timer_data == NULL) { - printf("out of memory : add_timer timer_data\n"); - exit(1); - } - memset(timer_data + (timer_data_max - 256), 0, - sizeof(struct TimerData) * 256); + //REALLOC(timer_data, struct TimerData, timer_data_max); + timer_data = (struct TimerData *) aRealloc( timer_data, sizeof(struct TimerData) * timer_data_max); + memset(timer_data + (timer_data_max - 256), 0, sizeof(struct TimerData) * 256); } - for(j = timer_data_max-256;j<timer_data_max; j++) - timer_data[j].type = 0; } td = &timer_data[i]; td->tick = tick; @@ -209,88 +196,79 @@ int add_timer(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int push_timer_heap(i); if (i >= timer_data_num) timer_data_num = i + 1; + return i; } -int add_timer_interval(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int data,int interval) -{ +int add_timer_interval(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int data,int interval) { int tid; + tid = add_timer(tick,func,id,data); timer_data[tid].type = TIMER_INTERVAL; timer_data[tid].interval = interval; + return tid; } -int delete_timer(int id,int (*func)(int,unsigned int,int,int)) -{ +int delete_timer(int id,int (*func)(int,unsigned int,int,int)) { if (id <= 0 || id >= timer_data_num) { printf("delete_timer error : no such timer %d\n", id); return -1; } if (timer_data[id].func != func) { printf("delete_timer error : function dismatch %08x(%s) != %08x(%s)\n", - (int)timer_data[id].func, - search_timer_func_list(timer_data[id].func), - (int)func, - search_timer_func_list(func)); + (int)timer_data[id].func, search_timer_func_list(timer_data[id].func), + (int)func, search_timer_func_list(func)); return -2; } // ‚»‚Ì‚¤‚¿Á‚¦‚é‚ɂ܂©‚¹‚é timer_data[id].func = NULL; timer_data[id].type = TIMER_ONCE_AUTODEL; - timer_data[id].tick -= 60 * 60 * 1000; +// timer_data[id].tick -= 60 * 60 * 1000; + return 0; } -int addtick_timer(int tid,unsigned int tick) -{ +int addtick_timer(int tid,unsigned int tick) { return timer_data[tid].tick += tick; } -struct TimerData* get_timer(int tid) -{ + +struct TimerData* get_timer(int tid) { return &timer_data[tid]; } +int do_timer(unsigned int tick) { + int i, nextmin = 1000; -int do_timer(unsigned int tick) -{ - int i,nextmin = 1000; - -#if 0 - static int disp_tick = 0; - if (DIFF_TICK(disp_tick,tick)<-5000 || DIFF_TICK(disp_tick,tick)>5000) { - printf("timer %d(%d + %d)\n",timer_data_num,timer_heap[0],free_timer_list_pos); - disp_tick = tick; - } -#endif - - while((i = top_timer_heap()) >= 0) { - if (DIFF_TICK(timer_data[i].tick , tick)>0) { - nextmin = DIFF_TICK(timer_data[i].tick , tick); + while(timer_heap_num) { + i = timer_heap[timer_heap_num - 1]; // next shorter element + if (DIFF_TICK(timer_data[i].tick, tick) > 0) { + nextmin = DIFF_TICK(timer_data[i].tick, tick); break; } - pop_timer_heap(); + if (timer_heap_num > 0) // suppress the actual element from the table + timer_heap_num--; timer_data[i].type |= TIMER_REMOVE_HEAP; if (timer_data[i].func) { - if (DIFF_TICK(timer_data[i].tick , tick) < -1000) { + if (DIFF_TICK(timer_data[i].tick, tick) < -1000) { // 1•bˆÈã‚̑啂Ȓx‰„‚ª”¶‚µ‚Ä‚¢‚é‚Ì‚ÅA // timerˆ—ƒ^ƒCƒ~ƒ“ƒO‚ðŒ»Ý’l‚Æ‚·‚鎖‚Å // ŒÄ‚Ño‚µŽžƒ^ƒCƒ~ƒ“ƒO(ˆø”‚Ìtick)‘Š‘Î‚Åˆ—‚µ‚Ä‚é // timerŠÖ”‚ÌŽŸ‰ñˆ—ƒ^ƒCƒ~ƒ“ƒO‚ð’x‚点‚é - timer_data[i].func(i,tick,timer_data[i].id,timer_data[i].data); + timer_data[i].func(i, tick, timer_data[i].id, timer_data[i].data); } else { - timer_data[i].func(i,timer_data[i].tick,timer_data[i].id,timer_data[i].data); + timer_data[i].func(i, timer_data[i].tick, timer_data[i].id, timer_data[i].data); } } - if (timer_data[i].type&TIMER_REMOVE_HEAP) { + if (timer_data[i].type & TIMER_REMOVE_HEAP) { switch(timer_data[i].type & ~TIMER_REMOVE_HEAP) { case TIMER_ONCE_AUTODEL: timer_data[i].type = 0; if (free_timer_list_pos >= free_timer_list_max) { free_timer_list_max += 256; - RECREATE(free_timer_list, int, free_timer_list_max); - memset(free_timer_list + (free_timer_list_max - 256), 0, - 256 * sizeof(free_timer_list[0])); + //REALLOC(free_timer_list, int, free_timer_list_max); + free_timer_list = (int *) aRealloc(free_timer_list, sizeof(int) * free_timer_list_max); + memset(free_timer_list + (free_timer_list_max - 256), 0, 256 * sizeof(int)); } free_timer_list[free_timer_list_pos++] = i; break; @@ -307,13 +285,31 @@ int do_timer(unsigned int tick) } } - if(nextmin < TIMER_MIN_INTERVEL) + if (nextmin < 10) + nextmin = 10; - nextmin = TIMER_MIN_INTERVEL; return nextmin; } -void timer_final() -{ - free(timer_data); +void timer_final() { + struct timer_func_list* tfl = tfl_root, *tfl2; + +// while (tfl) { +// tfl2 = tfl; +// aFree(tfl->name); +// aFree(tfl); +// tfl = tfl2->next; // access on already freed memory +// } + + while (tfl) { + tfl2 = tfl->next; // copy next pointer + aFree(tfl->name); // free structures + aFree(tfl); + tfl = tfl2; // use copied pointer for next cycle + } + + if (timer_data) aFree(timer_data); + if (timer_heap) aFree(timer_heap); + if (free_timer_list) aFree(free_timer_list); } + diff --git a/src/common/timer.h b/src/common/timer.h index f6fc5c84d..81086cb70 100644 --- a/src/common/timer.h +++ b/src/common/timer.h @@ -3,6 +3,12 @@ #ifndef _TIMER_H_ #define _TIMER_H_ +#ifdef __WIN32 +/* We need winsock lib to have timeval struct - windows is weirdo */ +#define __USE_W32_SOCKETS +#include <windows.h> +#endif + #define BASE_TICK 5 #define TIMER_ONCE_AUTODEL 1 @@ -25,6 +31,10 @@ struct TimerData { // Function prototype declaration +#ifdef __WIN32 +void gettimeofday(struct timeval *t, void *dummy); +#endif + unsigned int gettick_nocache(void); unsigned int gettick(void); @@ -40,6 +50,6 @@ int do_timer(unsigned int tick); int add_timer_func_list(int (*)(int,unsigned int,int,int),char*); char* search_timer_func_list(int (*)(int,unsigned int,int,int)); -extern void timer_final(); +void timer_final(); #endif // _TIMER_H_ diff --git a/src/common/utils.c b/src/common/utils.c index 2a09f773e..732b1d366 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -1,8 +1,10 @@ #include <string.h> #include "utils.h" #include <stdio.h> -#include <stdlib.h> #include <stdarg.h> +#include <stdlib.h> +#include "malloc.h" +#include "mmo.h" void dump(unsigned char *buffer, int num) { @@ -111,7 +113,7 @@ void str_lower(char *name) // Allocate a StringBuf [MouseJstr] struct StringBuf * StringBuf_Malloc() { - struct StringBuf * ret = (struct StringBuf *) malloc(sizeof(struct StringBuf)); + struct StringBuf * ret = (struct StringBuf *) aMallocA(sizeof(struct StringBuf)); StringBuf_Init(ret); return ret; } @@ -119,7 +121,7 @@ struct StringBuf * StringBuf_Malloc() // Initialize a previously allocated StringBuf [MouseJstr] void StringBuf_Init(struct StringBuf * sbuf) { sbuf->max_ = 1024; - sbuf->ptr_ = sbuf->buf_ = (char *) malloc(sbuf->max_ + 1); + sbuf->ptr_ = sbuf->buf_ = (char *) aMallocA(sbuf->max_ + 1); } // printf into a StringBuf, moving the pointer [MouseJstr] @@ -142,7 +144,7 @@ int StringBuf_Printf(struct StringBuf *sbuf,const char *fmt,...) /* Else try again with more space. */ sbuf->max_ *= 2; // twice the old size off = sbuf->ptr_ - sbuf->buf_; - sbuf->buf_ = (char *) realloc(sbuf->buf_, sbuf->max_ + 1); + sbuf->buf_ = (char *) aRealloc(sbuf->buf_, sbuf->max_ + 1); sbuf->ptr_ = sbuf->buf_ + off; } } @@ -156,7 +158,7 @@ int StringBuf_Append(struct StringBuf *buf1,const struct StringBuf *buf2) if (size2 >= buf1_avail) { int off = buf1->ptr_ - buf1->buf_; buf1->max_ += size2; - buf1->buf_ = (char *) realloc(buf1->buf_, buf1->max_ + 1); + buf1->buf_ = (char *) aRealloc(buf1->buf_, buf1->max_ + 1); buf1->ptr_ = buf1->buf_ + off; } @@ -168,7 +170,7 @@ int StringBuf_Append(struct StringBuf *buf1,const struct StringBuf *buf2) // Destroy a StringBuf [MouseJstr] void StringBuf_Destroy(struct StringBuf *sbuf) { - free(sbuf->buf_); + aFree(sbuf->buf_); sbuf->ptr_ = sbuf->buf_ = 0; } @@ -176,7 +178,7 @@ void StringBuf_Destroy(struct StringBuf *sbuf) void StringBuf_Free(struct StringBuf *sbuf) { StringBuf_Destroy(sbuf); - free(sbuf); + aFree(sbuf); } // Return the built string from the StringBuf [MouseJstr] diff --git a/src/common/utils.h b/src/common/utils.h index 248bcd867..63c3f21ec 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -1,5 +1,6 @@ -#ifndef UTILS_H -#define UTILS_H +#ifndef COMMON_UTILS_H +#define COMMON_UTILS_H + #ifndef NULL #define NULL (void *)0 @@ -20,16 +21,23 @@ #endif -void dump(unsigned char *buffer, int num); + void dump(unsigned char *buffer, int num); + #define CREATE(result, type, number) do {\ if ((number) * sizeof(type) <= 0) \ printf("SYSERR: Zero bytes or less requested at %s:%d.\n", __FILE__, __LINE__); \ - if (!((result) = (type *) calloc ((number), sizeof(type)))) \ + if (!((result) = (type *) aCalloc ((number), sizeof(type)))) \ + { perror("SYSERR: malloc failure"); abort(); } } while(0) + +#define CREATE_A(result, type, number) do {\ + if ((number) * sizeof(type) <= 0) \ + printf("SYSERR: Zero bytes or less requested at %s:%d.\n", __FILE__, __LINE__); \ + if (!((result) = (type *) aCallocA ((number), sizeof(type)))) \ { perror("SYSERR: malloc failure"); abort(); } } while(0) #define RECREATE(result,type,number) do {\ - if (!((result) = (type *) realloc ((result), sizeof(type) * (number))))\ + if (!((result) = (type *) aRealloc ((result), sizeof(type) * (number))))\ { printf("SYSERR: realloc failure"); abort(); } } while(0) struct StringBuf { diff --git a/src/ladmin/GNUmakefile b/src/ladmin/GNUmakefile deleted file mode 100644 index 879edaeea..000000000 --- a/src/ladmin/GNUmakefile +++ /dev/null @@ -1,14 +0,0 @@ -all: ladmin -txt: ladmin -sql: ladmin - -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/malloc.h ../common/showmsg.h - -ladmin: ladmin.o md5calc.o $(COMMON_OBJ) - $(CC) -o ../../$@ ladmin.o md5calc.o $(COMMON_OBJ) -ladmin.o: ladmin.c ladmin.h md5calc.h $(COMMON_H) -md5calc.o: md5calc.c md5calc.h - -clean: - rm -f *.o ../../ladmin diff --git a/src/ladmin/Makefile b/src/ladmin/Makefile index 879edaeea..20722350b 100644 --- a/src/ladmin/Makefile +++ b/src/ladmin/Makefile @@ -2,11 +2,11 @@ all: ladmin txt: ladmin sql: ladmin -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/malloc.h ../common/showmsg.h +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o +COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h ladmin: ladmin.o md5calc.o $(COMMON_OBJ) - $(CC) -o ../../$@ ladmin.o md5calc.o $(COMMON_OBJ) + $(CC) -o ../../$@ ladmin.o md5calc.o $(COMMON_OBJ) $(LIB_S) ladmin.o: ladmin.c ladmin.h md5calc.h $(COMMON_H) md5calc.o: md5calc.c md5calc.h diff --git a/src/ladmin/ladmin.c b/src/ladmin/ladmin.c index 497f3bdab..432a78a95 100644 --- a/src/ladmin/ladmin.c +++ b/src/ladmin/ladmin.c @@ -6,27 +6,42 @@ /////////////////////////////////////////////////////////////////////////// #include <sys/types.h> +#include <time.h> +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include <winsock2.h> +void Gettimeofday(struct timeval *timenow) +{ + time_t t; + t = clock(); + timenow->tv_usec = t; + timenow->tv_sec = t / CLK_TCK; + return; +} +#define gettimeofday(timenow, dummy) Gettimeofday(timenow) +#else #include <sys/socket.h> -#include <stdio.h> -#include <stdlib.h> #include <netinet/in.h> #include <sys/time.h> // gettimeofday -#include <time.h> #include <sys/ioctl.h> #include <unistd.h> // close +#include <arpa/inet.h> // inet_addr +#include <netdb.h> // gethostbyname +#endif +#include <stdio.h> +#include <stdlib.h> #include <signal.h> #include <fcntl.h> #include <string.h> // str* -#include <arpa/inet.h> // inet_addr -#include <netdb.h> // gethostbyname #include <stdarg.h> // valist #include <ctype.h> // tolower -#include "core.h" -#include "socket.h" +#include "../common/strlib.h" +#include "../common/core.h" +#include "../common/socket.h" #include "ladmin.h" -#include "version.h" -#include "mmo.h" +#include "../common/version.h" +#include "../common/mmo.h" #ifdef PASSWORDENC #include "md5calc.h" @@ -266,7 +281,7 @@ int ladmin_log(char *fmt, ...) { fprintf(logfp, RETCODE); else { gettimeofday(&tv, NULL); - strftime(tmpstr, 24, date_format, localtime(&(tv.tv_sec))); + strftime(tmpstr, 24, date_format, localtime((const time_t*)&(tv.tv_sec))); sprintf(tmpstr + strlen(tmpstr), ".%03d: %s", (int)tv.tv_usec / 1000, fmt); vfprintf(logfp, tmpstr, ap); } @@ -277,23 +292,6 @@ int ladmin_log(char *fmt, ...) { return 0; } -//----------------------------------------------------- -// Function to suppress control characters in a string. -//----------------------------------------------------- -int remove_control_chars(unsigned char *str) { - int i; - int change = 0; - - for(i = 0; str[i]; i++) { - if (str[i] < 32) { - str[i] = '_'; - change = 1; - } - } - - return change; -} - //--------------------------------------------- // Function to return ordonal text of a number. //--------------------------------------------- @@ -367,9 +365,9 @@ int verify_accountname(char* account_name) { //--------------------------------------------------- // E-mail check: return 0 (not correct) or 1 (valid). //--------------------------------------------------- -int e_mail_check(unsigned char *email) { +int e_mail_check(char *email) { char ch; - unsigned char* last_arobas; + char* last_arobas; // athena limits if (strlen(email) < 3 || strlen(email) > 39) @@ -3252,7 +3250,7 @@ int parse_fromlogin(int fd) { } // printf("parse_fromlogin : %d %d %d\n", fd, RFIFOREST(fd), RFIFOW(fd,0)); - sd = session[fd]->session_data; + sd = (struct char_session_data*)session[fd]->session_data; while(RFIFOREST(fd) >= 2) { switch(RFIFOW(fd,0)) { @@ -3302,11 +3300,11 @@ int parse_fromlogin(int fd) { memcpy(md5key, RFIFOP(fd,4), RFIFOW(fd,2) - 4); md5key[sizeof(md5key)-1] = '0'; if (passenc == 1) { - strncpy(md5str, RFIFOP(fd,4), RFIFOW(fd,2) - 4); + strncpy(md5str, (const char*)RFIFOP(fd,4), RFIFOW(fd,2) - 4); strcat(md5str, loginserveradminpassword); } else if (passenc == 2) { strncpy(md5str, loginserveradminpassword, sizeof(loginserveradminpassword)); - strcat(md5str, RFIFOP(fd,4)); + strcat(md5str, (const char*)RFIFOP(fd,4)); } MD5_String2binary(md5str, md5bin); WFIFOW(login_fd,0) = 0x7918; // Request for administation login (encrypted password) @@ -3801,7 +3799,7 @@ int parse_fromlogin(int fd) { case 0x7947: // answer of an account name search if (RFIFOREST(fd) < 30) return 0; - if (strcmp(RFIFOP(fd,6), "") == 0) { + if (strcmp((const char*)RFIFOP(fd,6), "") == 0) { if (defaultlanguage == 'F') { printf("Impossible de trouver le nom du compte [%d]. Le compte n'existe pas.\n", RFIFOL(fd,2)); ladmin_log("Impossible de trouver le nom du compte [%d]. Le compte n'existe pas." RETCODE, RFIFOL(fd,2)); @@ -4018,7 +4016,7 @@ int parse_fromlogin(int fd) { connect_until_time = (time_t)RFIFOL(fd,140); ban_until_time = (time_t)RFIFOL(fd,144); memset(memo, '\0', sizeof(memo)); - strncpy(memo, RFIFOP(fd,150), RFIFOW(fd,148)); + strncpy(memo, (const char*)RFIFOP(fd,150), RFIFOW(fd,148)); if (RFIFOL(fd,2) == -1) { if (defaultlanguage == 'F') { printf("Impossible de trouver le compte [%s]. Le compte n'existe pas.\n", parameters); @@ -4258,8 +4256,8 @@ int ladmin_config_read(const char *cfgName) { line[sizeof(line)-1] = '\0'; if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) { - remove_control_chars(w1); - remove_control_chars(w2); + remove_control_chars((unsigned char *) w1); + remove_control_chars((unsigned char *) w2); if(strcmpi(w1,"login_ip")==0){ struct hostent *h = gethostbyname (w2); diff --git a/src/ladmin/md5calc.c b/src/ladmin/md5calc.c index 7b9a9a2c6..c6c958583 100644 --- a/src/ladmin/md5calc.c +++ b/src/ladmin/md5calc.c @@ -96,7 +96,7 @@ static void MD5_Round_Calculate(const unsigned char *block, //Save A as AA, B as BB, C as CC, and and D as DD (saving of A, B, C, and D) unsigned int A=*A2, B=*B2, C=*C2, D=*D2; unsigned int AA = A,BB = B,CC = C,DD = D; - + //It is a large region variable reluctantly because of calculation of a round. . . for Round1...4 pX = X; @@ -187,7 +187,7 @@ void MD5_String2binary(const char * string, char * output) memset(padding_message+copy_len, 0, 64 - copy_len); //It buries by 0 until it becomes extended bit length. padding_message[copy_len] |= 0x80; //The next of a message is 1. - //1-4 + //1-4 //If 56 bytes or more (less than 64 bytes) of remainder becomes, it will calculate by extending to 64 bytes. if (56 <= copy_len) { MD5_Round_Calculate(padding_message, A,B,C,D); @@ -226,7 +226,7 @@ void MD5_String(const char * string, char * output) { unsigned char digest[16]; - MD5_String2binary(string,digest); + MD5_String2binary(string,(char*)digest); sprintf(output, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", digest[ 0], digest[ 1], digest[ 2], digest[ 3], diff --git a/src/lib/zconf_win32.h b/src/lib/zconf_win32.h new file mode 100644 index 000000000..6d450fc79 --- /dev/null +++ b/src/lib/zconf_win32.h @@ -0,0 +1,279 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#if defined(MSDOS) && !defined(__32BIT__) +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) +# define STDC +#endif +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Old Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) +# define NEED_DUMMY_RETURN +#endif + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +#endif +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +# ifndef __32BIT__ +# define SMALL_MEDIUM +# define FAR _far +# endif +#endif + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if defined(ZLIB_DLL) +# if defined(_WINDOWS) || defined(WINDOWS) +# ifdef FAR +# undef FAR +# endif +# include <windows.h> +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR _cdecl _export +# endif +# endif +# if defined (__BORLANDC__) +# if (__BORLANDC__ >= 0x0500) && defined (WIN32) +# include <windows.h> +# define ZEXPORT __declspec(dllexport) WINAPI +# define ZEXPORTRVA __declspec(dllexport) WINAPIV +# else +# if defined (_Windows) && defined (__DLL__) +# define ZEXPORT _export +# define ZEXPORTVA _export +# endif +# endif +# endif +#endif + +#if defined (__BEOS__) +# if defined (ZLIB_DLL) +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +#endif + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(MACOS) && !defined(TARGET_OS_MAC) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H +# include <sys/types.h> /* for off_t */ +# include <unistd.h> /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") +#endif + +#endif /* _ZCONF_H */ diff --git a/src/lib/zlib_win32.h b/src/lib/zlib_win32.h new file mode 100644 index 000000000..3cd63c939 --- /dev/null +++ b/src/lib/zlib_win32.h @@ -0,0 +1,893 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.3, July 9th, 1998 + + Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include "zconf_win32.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.1.3" + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least 0.1% larger than + sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + const voidp buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/src/login/GNUmakefile b/src/login/GNUmakefile deleted file mode 100644 index 300737cbf..000000000 --- a/src/login/GNUmakefile +++ /dev/null @@ -1,13 +0,0 @@ -all: login-server -txt: login-server - -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/lock.o ../common/malloc.o ../common/showmsg.o -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/lock.h ../common/malloc.h ../common/showmsg.h - -login-server: login.o md5calc.o $(COMMON_OBJ) - $(CC) -o ../../$@ login.o md5calc.o $(COMMON_OBJ) -login.o: login.c login.h md5calc.h $(COMMON_H) -md5calc.o: md5calc.c md5calc.h - -clean: - rm -f *.o ../../login-server diff --git a/src/login/Makefile b/src/login/Makefile index 300737cbf..01810b1d1 100644 --- a/src/login/Makefile +++ b/src/login/Makefile @@ -1,11 +1,12 @@ all: login-server txt: login-server -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/lock.o ../common/malloc.o ../common/showmsg.o -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/lock.h ../common/malloc.h ../common/showmsg.h +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/lock.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o +COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/lock.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h login-server: login.o md5calc.o $(COMMON_OBJ) - $(CC) -o ../../$@ login.o md5calc.o $(COMMON_OBJ) + $(CC) -o ../../$@ login.o md5calc.o $(COMMON_OBJ) $(LIB_S) + login.o: login.c login.h md5calc.h $(COMMON_H) md5calc.o: md5calc.c md5calc.h diff --git a/src/login/login.c b/src/login/login.c index 8d7ce12a2..733411f56 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -2,20 +2,36 @@ // new version of the login-server by [Yor] #include <sys/types.h> +#ifdef __WIN32 +#define WIN32_LEAN_AND_MEAN +#include <winsock2.h> +#include <time.h> +void Gettimeofday(struct timeval *timenow) +{ + time_t t; + t = clock(); + timenow->tv_usec = t; + timenow->tv_sec = t / CLK_TCK; + return; +} +#define gettimeofday(timenow, dummy) Gettimeofday(timenow) +#define in_addr_t unsigned long +#else #include <sys/socket.h> -#include <stdio.h> -#include <stdlib.h> #include <netinet/in.h> #include <sys/time.h> -#include <time.h> #include <sys/ioctl.h> -#include <sys/stat.h> // for stat/lstat/fstat #include <unistd.h> +#include <arpa/inet.h> +#include <netdb.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <sys/stat.h> // for stat/lstat/fstat #include <signal.h> #include <fcntl.h> #include <string.h> -#include <arpa/inet.h> -#include <netdb.h> #include <stdarg.h> #include "../common/core.h" @@ -27,6 +43,8 @@ #include "../common/db.h" #include "../common/lock.h" #include "../common/malloc.h" +#include "../common/buffer.h" +#include "../common/strlib.h" #ifdef PASSWORDENC #include "md5calc.h" @@ -39,6 +57,8 @@ int account_id_count = START_ACCOUNT_NUM; int server_num; int new_account_flag = 0; +char bind_ip_str[16]; +in_addr_t bind_ip; int login_port = 6900; char lan_char_ip[16]; int subneti[4]; @@ -54,15 +74,14 @@ int save_unknown_packets = 0; long creation_time_GM_account_file; int gm_account_filename_check_timer = 15; // Timer to check if GM_account file has been changed and reload GM account automaticaly (in seconds; default: 15) +int log_login = 1; + int display_parse_login = 0; // 0: no, 1: yes int display_parse_admin = 0; // 0: no, 1: yes int display_parse_fromchar = 0; // 0: no, 1: yes (without packet 0x2714), 2: all packets struct mmo_char_server server[MAX_SERVERS]; int server_fd[MAX_SERVERS]; -int server_freezeflag[MAX_SERVERS]; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed -int anti_freeze_enable = 0; -int ANTI_FREEZE_INTERVAL = 15; int login_fd; @@ -94,6 +113,11 @@ int add_to_unlimited_account = 0; // Give possibility or not to adjust (ladmin c int start_limited_time = -1; // Starting additional sec from now for the limited time at creation of accounts (-1: unlimited time, 0 or more: additional sec from now) int check_ip_flag = 1; // It's to check IP of a player between login-server and char-server (part of anti-hacking system) +int check_client_version = 0; //Client version check ON/OFF .. (sirius) +int client_version_to_connect = 20; //Client version needed to connect ..(sirius) + + + struct login_session_data { int md5keylen; char md5key[20]; @@ -141,6 +165,8 @@ int level_new_gm = 60; struct gm_account *gm_account_db; +static struct dbt *online_db; + int dynamic_pass_failure_ban = 1; int dynamic_pass_failure_ban_time = 5; int dynamic_pass_failure_ban_how_many = 3; @@ -154,31 +180,52 @@ int console = 0; // Writing function of logs file //------------------------------ int login_log(char *fmt, ...) { - va_list ap; - struct timeval tv; - char tmpstr[2048]; + if (log_login) { + va_list ap; + struct timeval tv; + char tmpstr[2048]; - if(!log_fp) - log_fp = fopen(login_log_filename, "a"); + if(!log_fp) + log_fp = fopen(login_log_filename, "a"); - log_fp = fopen(login_log_filename, "a"); - if (log_fp) { - if (fmt[0] == '\0') // jump a line if no message - fprintf(log_fp, RETCODE); - else { - va_start(ap, fmt); - gettimeofday(&tv, NULL); - strftime(tmpstr, 24, date_format, localtime(&(tv.tv_sec))); - sprintf(tmpstr + strlen(tmpstr), ".%03d: %s", (int)tv.tv_usec / 1000, fmt); - vfprintf(log_fp, tmpstr, ap); - va_end(ap); + if (log_fp) { + if (fmt[0] == '\0') // jump a line if no message + fprintf(log_fp, RETCODE); + else { + va_start(ap, fmt); + gettimeofday(&tv, NULL); + strftime(tmpstr, 24, date_format, localtime((const time_t*)&(tv.tv_sec))); + sprintf(tmpstr + strlen(tmpstr), ".%03d: %s", (int)tv.tv_usec / 1000, fmt); + vfprintf(log_fp, tmpstr, ap); + va_end(ap); + } + fflush(log_fp); // under cygwin or windows, if software is stopped, data are not written in the file -> fflush at every line } - fflush(log_fp); // under cygwin or windows, if software is stopped, data are not written in the file -> fflush at every line } return 0; } +//----------------------------------------------------- +// Online User Database [Wizputer] +//----------------------------------------------------- + +void add_online_user (int account_id) { + int *p; + p = (int *)aMalloc(sizeof(int)); + *p = account_id; + numdb_insert(online_db, account_id, p); +} +int is_user_online (int account_id) { + int *p = (int*)numdb_search(online_db, account_id); + return (p != NULL); +} +void remove_online_user (int account_id) { + int *p; + p = (int*)numdb_erase(online_db, account_id); + aFree(p); +} + //---------------------------------------------------------------------- // Determine if an account (id) is a GM account // and returns its level (or 0 if it isn't a GM account or if not found) @@ -213,12 +260,12 @@ void addGM(int account_id, int level) { } return; } - + // if new account if (i == GM_num && do_add) { if (GM_num >= GM_max) { GM_max += 256; - gm_account_db = realloc(gm_account_db, sizeof(struct gm_account) * GM_max); + gm_account_db = (struct gm_account*)aRealloc(gm_account_db, sizeof(struct gm_account) * GM_max); memset(gm_account_db + (GM_max - 256), 0, sizeof(struct gm_account) * 256); } gm_account_db[GM_num].account_id = account_id; @@ -242,7 +289,7 @@ int read_gm_account() { struct stat file_stat; int start_range = 0, end_range = 0, is_range = 0, current_id = 0; - if(gm_account_db) free(gm_account_db); + if(gm_account_db) aFree(gm_account_db); GM_num = 0; if(GM_max < 0) GM_max = 256; gm_account_db = (struct gm_account*)aCalloc(GM_max, sizeof(struct gm_account)); @@ -283,7 +330,7 @@ int read_gm_account() { printf("read_gm_account: file [%s] invalid range, beginning of range is equal to end of range (line #%d).\n", GM_account_filename, line_counter); else if (start_range>end_range) printf("read_gm_account: file [%s] invalid range, beginning of range must be lower than end of range (line #%d).\n", GM_account_filename, line_counter); - else + else for (current_id = start_range;current_id<=end_range;current_id++) addGM(current_id,level); } else { @@ -307,14 +354,14 @@ int check_ipmask(unsigned int ip, const unsigned char *str) { unsigned int mask = 0, i = 0, m, ip2, a0, a1, a2, a3; unsigned char *p = (unsigned char *)&ip2, *p2 = (unsigned char *)&mask; - if (sscanf(str, "%d.%d.%d.%d/%n", &a0, &a1, &a2, &a3, &i) != 4 || i == 0) + if (sscanf((const char*)str, "%d.%d.%d.%d/%n", &a0, &a1, &a2, &a3, &i) != 4 || i == 0) return 0; p[0] = a0; p[1] = a1; p[2] = a2; p[3] = a3; - if (sscanf(str+i, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) == 4) { + if (sscanf((const char*)str+i, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) == 4) { p2[0] = a0; p2[1] = a1; p2[2] = a2; p2[3] = a3; mask = ntohl(mask); - } else if (sscanf(str+i, "%d", &m) == 1 && m >= 0 && m <= 32) { + } else if (sscanf((const char*)(str+i), "%d", &m) == 1 && m >= 0 && m <= 32) { for(i = 0; i < m && i < 32; i++) mask = (mask >> 1) | 0x80000000; } else { @@ -353,7 +400,7 @@ int check_ip(unsigned int ip) { for(i = 0; i < access_allownum; i++) { access_ip = access_allow + i * ACO_STRSIZE; - if (memcmp(access_ip, buf, strlen(access_ip)) == 0 || check_ipmask(ip, access_ip)) { + if (memcmp(access_ip, buf, strlen(access_ip)) == 0 || check_ipmask(ip, (unsigned char*)access_ip)) { if(access_order == ACO_ALLOW_DENY) return 1; // With 'allow, deny' (deny if not allow), allow has priority flag = ACF_ALLOW; @@ -363,7 +410,7 @@ int check_ip(unsigned int ip) { for(i = 0; i < access_denynum; i++) { access_ip = access_deny + i * ACO_STRSIZE; - if (memcmp(access_ip, buf, strlen(access_ip)) == 0 || check_ipmask(ip, access_ip)) { + if (memcmp(access_ip, buf, strlen(access_ip)) == 0 || check_ipmask(ip, (unsigned char*)access_ip)) { //flag = ACF_DENY; // not necessary to define flag return 0; // At this point, if it's 'deny', we refuse connection. } @@ -401,7 +448,7 @@ int check_ladminip(unsigned int ip) { for(i = 0; i < access_ladmin_allownum; i++) { access_ip = access_ladmin_allow + i * ACO_STRSIZE; - if (memcmp(access_ip, buf, strlen(access_ip)) == 0 || check_ipmask(ip, access_ip)) { + if (memcmp(access_ip, buf, strlen(access_ip)) == 0 || check_ipmask(ip, (unsigned char*)access_ip)) { return 1; } } @@ -409,29 +456,12 @@ int check_ladminip(unsigned int ip) { return 0; } -//----------------------------------------------------- -// Function to suppress control characters in a string. -//----------------------------------------------------- -int remove_control_chars(unsigned char *str) { - int i; - int change = 0; - - for(i = 0; str[i]; i++) { - if (str[i] < 32) { - str[i] = '_'; - change = 1; - } - } - - return change; -} - //--------------------------------------------------- // E-mail check: return 0 (not correct) or 1 (valid). //--------------------------------------------------- -int e_mail_check(unsigned char *email) { +int e_mail_check(char *email) { char ch; - unsigned char* last_arobas; + char* last_arobas; // athena limits if (strlen(email) < 3 || strlen(email) > 39) @@ -577,7 +607,7 @@ int mmo_auth_init(void) { continue; } userid[23] = '\0'; - remove_control_chars(userid); + remove_control_chars((unsigned char *)userid); for(j = 0; j < auth_num; j++) { if (auth_dat[j].account_id == account_id) { printf("\033[1;31mmmo_auth_init: ******Error: an account has an identical id to another.\n"); @@ -590,8 +620,8 @@ int mmo_auth_init(void) { printf("\033[1;31mmmo_auth_init: ******Error: account name already exists.\n"); printf(" account name '%s' -> new account not read.\n", userid); // 2 lines, account name can be long. printf(" Account saved in log file.\033[0m\n"); - login_log("mmmo_auth_init: ******Error: an account has an identical id to another." RETCODE); - login_log(" account id #%d -> new account not read (saved in next line):" RETCODE, account_id); + login_log("mmmo_auth_init: ******Error: an account has an identical name to another." RETCODE); + login_log(" account name '%s' -> new account not read (saved in next line):" RETCODE, userid); login_log("%s", line); break; } @@ -601,7 +631,7 @@ int mmo_auth_init(void) { if (auth_num >= auth_max) { auth_max += 256; - auth_dat = realloc(auth_dat, sizeof(struct auth_dat) * auth_max); + auth_dat = (struct auth_dat*)aRealloc(auth_dat, sizeof(struct auth_dat) * auth_max); } memset(&auth_dat[auth_num], '\0', sizeof(struct auth_dat)); @@ -611,11 +641,11 @@ int mmo_auth_init(void) { strncpy(auth_dat[auth_num].userid, userid, 24); pass[23] = '\0'; - remove_control_chars(pass); + remove_control_chars((unsigned char *)pass); strncpy(auth_dat[auth_num].pass, pass, 24); lastlogin[23] = '\0'; - remove_control_chars(lastlogin); + remove_control_chars((unsigned char *)lastlogin); strncpy(auth_dat[auth_num].lastlogin, lastlogin, 24); auth_dat[auth_num].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm'); @@ -636,12 +666,12 @@ int mmo_auth_init(void) { printf("Account %s (%d): invalid e-mail (replaced par a@a.com).\n", auth_dat[auth_num].userid, auth_dat[auth_num].account_id); strncpy(auth_dat[auth_num].email, "a@a.com", 40); } else { - remove_control_chars(email); + remove_control_chars((unsigned char *)email); strncpy(auth_dat[auth_num].email, email, 40); } error_message[19] = '\0'; - remove_control_chars(error_message); + remove_control_chars((unsigned char *)error_message); if (error_message[0] == '\0' || state != 7) { // 7, because state is packet 0x006a value + 1 strncpy(auth_dat[auth_num].error_message, "-", 20); } else { @@ -656,11 +686,11 @@ int mmo_auth_init(void) { auth_dat[auth_num].connect_until_time = connect_until_time; last_ip[15] = '\0'; - remove_control_chars(last_ip); + remove_control_chars((unsigned char *)last_ip); strncpy(auth_dat[auth_num].last_ip, last_ip, 16); memo[254] = '\0'; - remove_control_chars(memo); + remove_control_chars((unsigned char *)memo); strncpy(auth_dat[auth_num].memo, memo, 255); for(j = 0; j < ACCOUNT_REG2_NUM; j++) { @@ -675,7 +705,7 @@ int mmo_auth_init(void) { break; } str[31] = '\0'; - remove_control_chars(str); + remove_control_chars((unsigned char *)str); strncpy(auth_dat[auth_num].account_reg2[j].str, str, 32); auth_dat[auth_num].account_reg2[j].value = v; } @@ -702,7 +732,7 @@ int mmo_auth_init(void) { continue; } userid[23] = '\0'; - remove_control_chars(userid); + remove_control_chars((unsigned char *)userid); for(j = 0; j < auth_num; j++) { if (auth_dat[j].account_id == account_id) { printf("\033[1;31mmmo_auth_init: ******Error: an account has an identical id to another.\n"); @@ -726,7 +756,7 @@ int mmo_auth_init(void) { if (auth_num >= auth_max) { auth_max += 256; - auth_dat = realloc(auth_dat, sizeof(struct auth_dat) * auth_max); + auth_dat = (struct auth_dat*)aRealloc(auth_dat, sizeof(struct auth_dat) * auth_max); } memset(&auth_dat[auth_num], '\0', sizeof(struct auth_dat)); @@ -736,11 +766,11 @@ int mmo_auth_init(void) { strncpy(auth_dat[auth_num].userid, userid, 24); pass[23] = '\0'; - remove_control_chars(pass); + remove_control_chars((unsigned char *)pass); strncpy(auth_dat[auth_num].pass, pass, 24); lastlogin[23] = '\0'; - remove_control_chars(lastlogin); + remove_control_chars((unsigned char *)lastlogin); strncpy(auth_dat[auth_num].lastlogin, lastlogin, 24); auth_dat[auth_num].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm'); @@ -783,7 +813,7 @@ int mmo_auth_init(void) { break; } str[31] = '\0'; - remove_control_chars(str); + remove_control_chars((unsigned char *)str); strncpy(auth_dat[auth_num].account_reg2[j].str, str, 32); auth_dat[auth_num].account_reg2[j].value = v; } @@ -852,7 +882,9 @@ void mmo_auth_sync(void) { FILE *fp; int i, j, k, lock; int account_id; - int id[auth_num]; + //int id[auth_num]; + //int *id = (int *)aCalloc(auth_num, sizeof(int)); + CREATE_BUFFER(id, int, auth_num); char line[65536]; // Sorting before save @@ -870,8 +902,11 @@ void mmo_auth_sync(void) { } // Data save - if ((fp = lock_fopen(account_filename, &lock)) == NULL) + if ((fp = lock_fopen(account_filename, &lock)) == NULL) { + //if (id) aFree(id); // aFree, right? + DELETE_BUFFER(id); return; + } fprintf(fp, "// Accounts file: here are saved all information about the accounts.\n"); fprintf(fp, "// Structure: ID, account name, password, last login time, sex, # of logins, state, email, error message for state 7, validity time, last (accepted) login ip, memo field, ban timestamp, repeated(register text, register value)\n"); @@ -902,6 +937,9 @@ void mmo_auth_sync(void) { if (auth_before_save_file < AUTH_BEFORE_SAVE_FILE) auth_before_save_file = AUTH_BEFORE_SAVE_FILE; + //if (id) aFree(id); + DELETE_BUFFER(id); + return; } @@ -947,7 +985,7 @@ int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) { //----------------------------------------------------- void send_GM_accounts() { int i; - char buf[32767]; + unsigned char buf[32767]; int len; len = 4; @@ -1000,8 +1038,7 @@ int mmo_auth_new(struct mmo_account* account, char sex, char* email) { if (auth_num >= auth_max) { auth_max += 256; - auth_dat = realloc(auth_dat, sizeof(struct auth_dat) * auth_max); - memset(auth_dat, 0, sizeof(struct auth_dat) * auth_max); + auth_dat = (struct auth_dat*)aRealloc(auth_dat, sizeof(struct auth_dat) * auth_max); } memset(&auth_dat[i], '\0', sizeof(struct auth_dat)); @@ -1086,7 +1123,14 @@ int mmo_auth(struct mmo_account* account, int fd) { newaccount = 1; account->userid[len] = '\0'; } - + + //EXE Version check [Sirius] + if(check_client_version == 1 && account->version != 0){ + if(account->version != client_version_to_connect){ + return 5; + } + } + // Strict account search for(i = 0; i < auth_num; i++) { if (strcmp(account->userid, auth_dat[i].userid) == 0) @@ -1113,7 +1157,7 @@ int mmo_auth(struct mmo_account* account, int fd) { memcpy(user_password, account->passwd, 25); encpasswdok = 0; #ifdef PASSWORDENC - ld = session[fd]->session_data; + ld = (struct login_session_data*)session[fd]->session_data; if (account->passwdenc > 0) { int j = account->passwdenc; if (!ld) { @@ -1215,7 +1259,7 @@ int mmo_auth(struct mmo_account* account, int fd) { } gettimeofday(&tv, NULL); - strftime(tmpstr, 24, date_format, localtime(&(tv.tv_sec))); + strftime(tmpstr, 24, date_format, localtime((const time_t*)&(tv.tv_sec))); sprintf(tmpstr + strlen(tmpstr), ".%03d", (int)tv.tv_usec / 1000); account->account_id = auth_dat[i].account_id; @@ -1235,32 +1279,6 @@ int mmo_auth(struct mmo_account* account, int fd) { return -1; // account OK } -//------------------------------- -// Char-server anti-freeze system -//------------------------------- -int char_anti_freeze_system(int tid, unsigned int tick, int id, int data) { - int i; - - //printf("Entering in char_anti_freeze_system function to check freeze of servers.\n"); - for(i = 0; i < MAX_SERVERS; i++) { - if (server_fd[i] >= 0) {// if char-server is online - //printf("char_anti_freeze_system: server #%d '%s', flag: %d.\n", i, server[i].name, server_freezeflag[i]); - if (server_freezeflag[i]-- < 1) { // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed - printf("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection.\n", i, server[i].name); - login_log("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection." RETCODE, - i, server[i].name); - session[server_fd[i]]->eof = 1; - } else { - // send alive packet to check connection - WFIFOW(server_fd[i],0) = 0x2718; - WFIFOSET(server_fd[i],2); - } - } - } - - return 0; -} - //-------------------------------- // Packet parsing for char-servers //-------------------------------- @@ -1367,13 +1385,15 @@ int parse_fromchar(int fd) { return 0; //printf("parse_fromchar: Receiving of the users number of the server '%s': %d\n", server[id].name, RFIFOL(fd,2)); server[id].users = RFIFOL(fd,2); - if(anti_freeze_enable) - server_freezeflag[id] = 5; // Char anti-freeze system. Counter. 5 ok, 4...0 freezed + // send some answer + WFIFOW(fd,0) = 0x2718; + WFIFOSET(fd,2); + RFIFOSKIP(fd,6); break; // we receive a e-mail creation of an account with a default e-mail (no answer) - case 0x2715: + case 0x2715: if (RFIFOREST(fd) < 46) return 0; { @@ -1381,7 +1401,7 @@ int parse_fromchar(int fd) { acc = RFIFOL(fd,2); // speed up memcpy(email, RFIFOP(fd,6), 40); email[39] = '\0'; - remove_control_chars(email); + remove_control_chars((unsigned char *)email); //printf("parse_fromchar: an e-mail creation of an account with a default e-mail: server '%s', account: %d, e-mail: '%s'.\n", server[id].name, acc, RFIFOP(fd,6)); if (e_mail_check(email) == 0) login_log("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - e-mail is invalid (account: %d, ip: %s)" RETCODE, @@ -1439,7 +1459,7 @@ int parse_fromchar(int fd) { WBUFW(buf,0) = 0x2721; WBUFL(buf,2) = acc; WBUFL(buf,6) = 0; - if (strcmp(RFIFOP(fd,8), gm_pass) == 0) { + if (strcmp((char*)RFIFOP(fd,8), gm_pass) == 0) { // only non-GM can become GM if (isGM(acc) == 0) { // if we autorise creation @@ -1449,7 +1469,7 @@ int parse_fromchar(int fd) { char tmpstr[24]; struct timeval tv; gettimeofday(&tv, NULL); - strftime(tmpstr, 23, date_format, localtime(&(tv.tv_sec))); + strftime(tmpstr, 23, date_format, localtime((const time_t*)&(tv.tv_sec))); fprintf(fp, RETCODE "// %s: @GM command on account %d" RETCODE "%d %d" RETCODE, tmpstr, acc, acc, level_new_gm); fclose(fp); WBUFL(buf,6) = level_new_gm; @@ -1492,10 +1512,10 @@ int parse_fromchar(int fd) { acc = RFIFOL(fd,2); memcpy(actual_email, RFIFOP(fd,6), 40); actual_email[39] = '\0'; - remove_control_chars(actual_email); + remove_control_chars((unsigned char *)actual_email); memcpy(new_email, RFIFOP(fd,46), 40); new_email[39] = '\0'; - remove_control_chars(new_email); + remove_control_chars((unsigned char *)new_email); if (e_mail_check(actual_email) == 0) login_log("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)" RETCODE, server[id].name, acc, ip); @@ -1682,13 +1702,15 @@ int parse_fromchar(int fd) { acc = RFIFOL(fd,4); for(i = 0; i < auth_num; i++) { if (auth_dat[i].account_id == acc) { - unsigned char buf[RFIFOW(fd,2)+1]; + //unsigned char buf[RFIFOW(fd,2)+1]; + unsigned char *buf; + buf = (unsigned char*)aCalloc(RFIFOW(fd,2)+1, sizeof(unsigned char)); login_log("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s)." RETCODE, server[id].name, acc, ip); for(p = 8, j = 0; p < RFIFOW(fd,2) && j < ACCOUNT_REG2_NUM; p += 36, j++) { memcpy(auth_dat[i].account_reg2[j].str, RFIFOP(fd,p), 32); auth_dat[i].account_reg2[j].str[31] = '\0'; - remove_control_chars(auth_dat[i].account_reg2[j].str); + remove_control_chars((unsigned char *)auth_dat[i].account_reg2[j].str); auth_dat[i].account_reg2[j].value = RFIFOL(fd,p+32); } auth_dat[i].account_reg2_num = j; @@ -1699,6 +1721,7 @@ int parse_fromchar(int fd) { // Save mmo_auth_sync(); // printf("parse_fromchar: receiving (from the char-server) of account_reg2 (account id: %d).\n", acc); + if (buf) free(buf); break; } } @@ -1735,6 +1758,21 @@ int parse_fromchar(int fd) { RFIFOSKIP(fd,6); } return 0; + + case 0x272b: // Set account_id to online [Wizputer] + if (RFIFOREST(fd) < 6) + return 0; + add_online_user(RFIFOL(fd,2)); + RFIFOSKIP(fd,6); + break; + + case 0x272c: // Set account_id to offline [Wizputer] + if (RFIFOREST(fd) < 6) + return 0; + remove_online_user(RFIFOL(fd,2)); + RFIFOSKIP(fd,6); + break; + case 0x3000: //change sex for chrif_changesex() if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; @@ -1774,7 +1812,7 @@ int parse_fromchar(int fd) { logfp = fopen(login_log_unknown_packets_filename, "a"); if (logfp) { gettimeofday(&tv, NULL); - strftime(tmpstr, 23, date_format, localtime(&(tv.tv_sec))); + strftime(tmpstr, 23, date_format, localtime((const time_t*)&(tv.tv_sec))); fprintf(logfp, "%s.%03d: receiving of an unknown packet -> disconnection" RETCODE, tmpstr, (int)tv.tv_usec / 1000); fprintf(logfp, "parse_fromchar: connection #%d (ip: %s), packet: 0x%x (with being read: %d)." RETCODE, fd, ip, RFIFOW(fd,0), RFIFOREST(fd)); fprintf(logfp, "Detail (in hex):" RETCODE); @@ -1864,7 +1902,9 @@ int parse_admin(int fd) { return 0; { int st, ed, len; - int id[auth_num]; + //int id[auth_num]; + //int *id=(int *)aCalloc(auth_num, sizeof(int)); + CREATE_BUFFER(id, int, auth_num); st = RFIFOL(fd,2); ed = RFIFOL(fd,6); RFIFOSKIP(fd,10); @@ -1908,6 +1948,8 @@ int parse_admin(int fd) { } WFIFOW(fd,2) = len; WFIFOSET(fd,len); + //if (id) free(id); + DELETE_BUFFER(id); } break; @@ -1916,13 +1958,13 @@ int parse_admin(int fd) { return 0; { struct mmo_account ma; - ma.userid = RFIFOP(fd, 2); + ma.userid = (char*)RFIFOP(fd, 2); memcpy(ma.passwd, RFIFOP(fd, 26), 24); ma.passwd[24] = '\0'; memcpy(ma.lastlogin, "-", 2); ma.sex = RFIFOB(fd,50); WFIFOW(fd,0) = 0x7931; - WFIFOL(fd,2) = -1; + WFIFOL(fd,2) = 0xffffffff; memcpy(WFIFOP(fd,6), RFIFOP(fd,2), 24); if (strlen(ma.userid) > 23 || strlen(ma.passwd) > 23) { login_log("'ladmin': Attempt to create an invalid account (account or pass is too long, ip: %s)" RETCODE, @@ -1937,8 +1979,8 @@ int parse_admin(int fd) { login_log("'ladmin': Attempt to create an account, but there is no more available id number (account: %s, pass: %s, sex: %c, ip: %s)" RETCODE, ma.userid, ma.passwd, ma.sex, ip); } else { - remove_control_chars(ma.userid); - remove_control_chars(ma.passwd); + remove_control_chars((unsigned char *)ma.userid); + remove_control_chars((unsigned char *)ma.passwd); for(i = 0; i < auth_num; i++) { if (strncmp(auth_dat[i].userid, ma.userid, 24) == 0) { login_log("'ladmin': Attempt to create an already existing account (account: %s, pass: %s, received pass: %s, ip: %s)" RETCODE, @@ -1951,7 +1993,7 @@ int parse_admin(int fd) { char email[40]; memcpy(email, RFIFOP(fd,51), 40); email[39] = '\0'; - remove_control_chars(email); + remove_control_chars((unsigned char *)email); new_id = mmo_auth_new(&ma, ma.sex, email); login_log("'ladmin': Account creation (account: %s (id: %d), pass: %s, sex: %c, email: %s, ip: %s)" RETCODE, ma.userid, new_id, ma.passwd, ma.sex, auth_dat[i].email, ip); @@ -1968,10 +2010,10 @@ int parse_admin(int fd) { if (RFIFOREST(fd) < 26) return 0; WFIFOW(fd,0) = 0x7933; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); i = search_account_index(account_name); if (i != -1) { // Char-server is notified of deletion (for characters deletion). @@ -1985,7 +2027,7 @@ int parse_admin(int fd) { // save deleted account in log file login_log("'ladmin': Account deletion (account: %s, id: %d, ip: %s) - saved in next line:" RETCODE, auth_dat[i].userid, auth_dat[i].account_id, ip); - mmo_auth_tostr(buf, &auth_dat[i]); + mmo_auth_tostr((char*)buf, &auth_dat[i]); login_log("%s" RETCODE, buf); // delete account memset(auth_dat[i].userid, '\0', sizeof(auth_dat[i].userid)); @@ -2004,16 +2046,16 @@ int parse_admin(int fd) { if (RFIFOREST(fd) < 50) return 0; WFIFOW(fd,0) = 0x7935; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; /// WTF??? an unsigned being set to a -1 + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); i = search_account_index(account_name); if (i != -1) { memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); memcpy(auth_dat[i].pass, RFIFOP(fd,26), 24); auth_dat[i].pass[23] = '\0'; - remove_control_chars(auth_dat[i].pass); + remove_control_chars((unsigned char *)auth_dat[i].pass); WFIFOL(fd,2) = auth_dat[i].account_id; login_log("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)" RETCODE, auth_dat[i].userid, auth_dat[i].pass, ip); @@ -2034,14 +2076,14 @@ int parse_admin(int fd) { char error_message[20]; int statut; WFIFOW(fd,0) = 0x7937; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); statut = RFIFOL(fd,26); memcpy(error_message, RFIFOP(fd,30), 20); error_message[19] = '\0'; - remove_control_chars(error_message); + remove_control_chars((unsigned char *)error_message); if (statut != 7 || error_message[0] == '\0') { // 7: // 6 = Your are Prohibited to log in until %s strcpy(error_message, "-"); } @@ -2095,7 +2137,7 @@ int parse_admin(int fd) { memcpy(WFIFOP(fd,4+server_num*32+6), server[i].name, 20); WFIFOW(fd,4+server_num*32+26) = server[i].users; WFIFOW(fd,4+server_num*32+28) = server[i].maintenance; - WFIFOW(fd,4+server_num*32+30) = server[i].new; + WFIFOW(fd,4+server_num*32+30) = server[i].new_; server_num++; } } @@ -2109,17 +2151,17 @@ int parse_admin(int fd) { if (RFIFOREST(fd) < 50) return 0; WFIFOW(fd,0) = 0x793b; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); i = search_account_index(account_name); if (i != -1) { char pass[25]; memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); memcpy(pass, RFIFOP(fd,26), 24); pass[24] = '\0'; - remove_control_chars(pass); + remove_control_chars((unsigned char *)pass); if (strcmp(auth_dat[i].pass, pass) == 0) { WFIFOL(fd,2) = auth_dat[i].account_id; login_log("'ladmin': Check of password OK (account: %s, password: %s, ip: %s)" RETCODE, @@ -2141,10 +2183,10 @@ int parse_admin(int fd) { if (RFIFOREST(fd) < 27) return 0; WFIFOW(fd,0) = 0x793d; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); memcpy(WFIFOP(fd,6), account_name, 24); { char sex; @@ -2193,10 +2235,10 @@ int parse_admin(int fd) { if (RFIFOREST(fd) < 27) return 0; WFIFOW(fd,0) = 0x793f; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); memcpy(WFIFOP(fd,6), account_name, 24); { char new_gm_level; @@ -2221,7 +2263,7 @@ int parse_admin(int fd) { if ((fp2 = lock_fopen(GM_account_filename, &lock)) != NULL) { if ((fp = fopen(GM_account_filename, "r")) != NULL) { gettimeofday(&tv, NULL); - strftime(tmpstr, 23, date_format, localtime(&(tv.tv_sec))); + strftime(tmpstr, 23, date_format, localtime((const time_t*)&(tv.tv_sec))); modify_flag = 0; // read/write GM file while(fgets(line, sizeof(line)-1, fp)) { @@ -2283,10 +2325,10 @@ int parse_admin(int fd) { if (RFIFOREST(fd) < 66) return 0; WFIFOW(fd,0) = 0x7941; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); memcpy(WFIFOP(fd,6), account_name, 24); { char email[40]; @@ -2295,7 +2337,7 @@ int parse_admin(int fd) { login_log("'ladmin': Attempt to give an invalid e-mail (account: %s, ip: %s)" RETCODE, account_name, ip); } else { - remove_control_chars(email); + remove_control_chars((unsigned char *)email); i = search_account_index(account_name); if (i != -1) { memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); @@ -2318,10 +2360,10 @@ int parse_admin(int fd) { if (RFIFOREST(fd) < 28 || RFIFOREST(fd) < (28 + RFIFOW(fd,26))) return 0; WFIFOW(fd,0) = 0x7943; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); i = search_account_index(account_name); if (i != -1) { int size_of_memo = sizeof(auth_dat[i].memo); @@ -2335,7 +2377,7 @@ int parse_admin(int fd) { memcpy(auth_dat[i].memo, RFIFOP(fd,28), RFIFOW(fd,26)); } auth_dat[i].memo[size_of_memo - 1] = '\0'; - remove_control_chars(auth_dat[i].memo); + remove_control_chars((unsigned char *)auth_dat[i].memo); WFIFOL(fd,2) = auth_dat[i].account_id; login_log("'ladmin': Modification of a memo field (account: %s, new memo: %s, ip: %s)" RETCODE, auth_dat[i].userid, auth_dat[i].memo, ip); @@ -2353,10 +2395,10 @@ int parse_admin(int fd) { if (RFIFOREST(fd) < 26) return 0; WFIFOW(fd,0) = 0x7945; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); i = search_account_index(account_name); if (i != -1) { memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); @@ -2380,7 +2422,7 @@ int parse_admin(int fd) { memset(WFIFOP(fd,6), '\0', 24); for(i = 0; i < auth_num; i++) { if (auth_dat[i].account_id == RFIFOL(fd,2)) { - strncpy(WFIFOP(fd,6), auth_dat[i].userid, 24); + strncpy((char*)WFIFOP(fd,6), auth_dat[i].userid, 24); login_log("'ladmin': Request (by id) of an account name (account: %s, id: %d, ip: %s)" RETCODE, auth_dat[i].userid, RFIFOL(fd,2), ip); break; @@ -2389,7 +2431,7 @@ int parse_admin(int fd) { if (i == auth_num) { login_log("'ladmin': Name request (by id) of an unknown account (id: %d, ip: %s)" RETCODE, RFIFOL(fd,2), ip); - strncpy(WFIFOP(fd,6), "", 24); + strncpy((char*)WFIFOP(fd,6), "", 24); } WFIFOSET(fd,30); RFIFOSKIP(fd,6); @@ -2402,10 +2444,10 @@ int parse_admin(int fd) { time_t timestamp; char tmpstr[2048]; WFIFOW(fd,0) = 0x7949; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); timestamp = (time_t)RFIFOL(fd,26); strftime(tmpstr, 24, date_format, localtime(×tamp)); i = search_account_index(account_name); @@ -2434,10 +2476,10 @@ int parse_admin(int fd) { time_t timestamp; char tmpstr[2048]; WFIFOW(fd,0) = 0x794b; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); timestamp = (time_t)RFIFOL(fd,26); if (timestamp <= time(NULL)) timestamp = 0; @@ -2482,10 +2524,10 @@ int parse_admin(int fd) { struct tm *tmtime; char tmpstr[2048]; WFIFOW(fd,0) = 0x794d; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); i = search_account_index(account_name); if (i != -1) { WFIFOL(fd,2) = auth_dat[i].account_id; @@ -2544,7 +2586,7 @@ int parse_admin(int fd) { if (RFIFOREST(fd) < 8 || RFIFOREST(fd) < (8 + RFIFOL(fd,4))) return 0; WFIFOW(fd,0) = 0x794f; - WFIFOW(fd,2) = -1; + WFIFOW(fd,2) = 0xFFFF; // WTF??? if (RFIFOL(fd,4) < 1) { login_log("'ladmin': Receiving a message for broadcast, but message is void (ip: %s)" RETCODE, ip); @@ -2557,13 +2599,13 @@ int parse_admin(int fd) { login_log("'ladmin': Receiving a message for broadcast, but no char-server is online (ip: %s)" RETCODE, ip); } else { - char buf[32000]; + unsigned char buf[32000]; char message[32000]; WFIFOW(fd,2) = 0; memset(message, '\0', sizeof(message)); memcpy(message, RFIFOP(fd,8), RFIFOL(fd,4)); message[sizeof(message)-1] = '\0'; - remove_control_chars(message); + remove_control_chars((unsigned char *)message); if (RFIFOW(fd,2) == 0) login_log("'ladmin': Receiving a message for broadcast (message (in yellow): %s, ip: %s)" RETCODE, message, ip); @@ -2589,10 +2631,10 @@ int parse_admin(int fd) { char tmpstr[2048]; char tmpstr2[2048]; WFIFOW(fd,0) = 0x7951; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); i = search_account_index(account_name); if (i != -1) { WFIFOL(fd,2) = auth_dat[i].account_id; @@ -2643,10 +2685,10 @@ int parse_admin(int fd) { if (RFIFOREST(fd) < 26) return 0; WFIFOW(fd,0) = 0x7953; - WFIFOL(fd,2) = -1; - account_name = RFIFOP(fd,2); + WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? + account_name = (char*)RFIFOP(fd,2); account_name[23] = '\0'; - remove_control_chars(account_name); + remove_control_chars((unsigned char *)account_name); i = search_account_index(account_name); if (i != -1) { WFIFOL(fd,2) = auth_dat[i].account_id; @@ -2710,7 +2752,7 @@ int parse_admin(int fd) { if (i == auth_num) { login_log("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)" RETCODE, RFIFOL(fd,2), ip); - strncpy(WFIFOP(fd,7), "", 24); + strncpy((char*)WFIFOP(fd,7), "", 24); WFIFOW(fd,148) = 0; WFIFOSET(fd,150); } @@ -2733,7 +2775,7 @@ int parse_admin(int fd) { logfp = fopen(login_log_unknown_packets_filename, "a"); if (logfp) { gettimeofday(&tv, NULL); - strftime(tmpstr, 23, date_format, localtime(&(tv.tv_sec))); + strftime(tmpstr, 23, date_format, localtime((const time_t*)&(tv.tv_sec))); fprintf(logfp, "%s.%03d: receiving of an unknown packet -> disconnection" RETCODE, tmpstr, (int)tv.tv_usec / 1000); fprintf(logfp, "parse_admin: connection #%d (ip: %s), packet: 0x%x (with being read: %d)." RETCODE, fd, ip, RFIFOW(fd,0), RFIFOREST(fd)); fprintf(logfp, "Detail (in hex):" RETCODE); @@ -2809,6 +2851,8 @@ int parse_login(int fd) { sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + memset(&account, 0, sizeof(account)); + if (session[fd]->eof) { close(fd); delete_session(fd); @@ -2826,7 +2870,7 @@ int parse_login(int fd) { } else printf("parse_login: connection #%d, packet: 0x%x (with being read: %d).\n", fd, RFIFOW(fd,0), RFIFOREST(fd)); } - + switch(RFIFOW(fd,0)) { case 0x200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive. if (RFIFOREST(fd) < 26) @@ -2844,10 +2888,11 @@ int parse_login(int fd) { case 0x01dd: // Ask connection of a client (encryption mode) if (RFIFOREST(fd) < ((RFIFOW(fd,0) == 0x64) ? 55 : 47)) return 0; - - account.userid = RFIFOP(fd,6); + + account.version = RFIFOL(fd, 2); //for exe version check [Sirius] + account.userid = (char*)RFIFOP(fd,6); account.userid[23] = '\0'; - remove_control_chars(account.userid); + remove_control_chars((unsigned char *)account.userid); if (RFIFOW(fd,0) == 0x64) { memcpy(account.passwd, RFIFOP(fd,30), 24); account.passwd[24] = '\0'; @@ -2855,7 +2900,7 @@ int parse_login(int fd) { memcpy(account.passwd, RFIFOP(fd,30), 32); account.passwd[32] = '\0'; } - remove_control_chars(account.passwd); + remove_control_chars((unsigned char *)account.passwd); #ifdef PASSWORDENC account.passwdenc = (RFIFOW(fd,0) == 0x64) ? 0 : PASSWORDENC; #else @@ -2901,7 +2946,7 @@ int parse_login(int fd) { memcpy(WFIFOP(fd,47+server_num*32+6), server[i].name, 20); WFIFOW(fd,47+server_num*32+26) = server[i].users; WFIFOW(fd,47+server_num*32+28) = server[i].maintenance; - WFIFOW(fd,47+server_num*32+30) = server[i].new; + WFIFOW(fd,47+server_num*32+30) = server[i].new_; server_num++; } } @@ -2965,7 +3010,8 @@ int parse_login(int fd) { session[fd]->eof = 1; return 0; } - ld = session[fd]->session_data = (struct login_session_data*)aCalloc(1, sizeof(struct login_session_data)); + ld = (struct login_session_data*)aCalloc(1, sizeof(struct login_session_data)); + session[fd]->session_data = ld; if (!ld) { printf("login: Request for md5 key: memory allocation failure (malloc)!\n"); session[fd]->eof = 1; @@ -2993,17 +3039,17 @@ int parse_login(int fd) { return 0; { int GM_value, len; - unsigned char* server_name; - account.userid = RFIFOP(fd,2); + char* server_name; + account.userid = (char*)RFIFOP(fd,2); account.userid[23] = '\0'; - remove_control_chars(account.userid); + remove_control_chars((unsigned char *)account.userid); memcpy(account.passwd, RFIFOP(fd,26), 24); account.passwd[24] = '\0'; - remove_control_chars(account.passwd); + remove_control_chars((unsigned char *)account.passwd); account.passwdenc = 0; - server_name = RFIFOP(fd,60); + server_name = (char*)RFIFOP(fd,60); server_name[19] = '\0'; - remove_control_chars(server_name); + remove_control_chars((unsigned char *)server_name); login_log("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (ip: %s)" RETCODE, server_name, RFIFOB(fd,54), RFIFOB(fd,55), RFIFOB(fd,56), RFIFOB(fd,57), RFIFOW(fd,58), ip); result = mmo_auth(&account, fd); @@ -3017,10 +3063,8 @@ int parse_login(int fd) { memcpy(server[account.account_id].name, server_name, 20); server[account.account_id].users = 0; server[account.account_id].maintenance = RFIFOW(fd,82); - server[account.account_id].new = RFIFOW(fd,84); + server[account.account_id].new_ = RFIFOW(fd,84); server_fd[account.account_id] = fd; - if(anti_freeze_enable) - server_freezeflag[account.account_id] = 5; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed WFIFOW(fd,0) = 0x2711; WFIFOB(fd,2) = 0; WFIFOSET(fd,3); @@ -3042,10 +3086,8 @@ int parse_login(int fd) { if (server_fd[account.account_id] != -1) { printf("Connection of the char-server '%s' REFUSED - already connected (account: %ld-%s, pass: %s, ip: %s)\n", server_name, account.account_id, account.userid, account.passwd, ip); - printf("You must probably wait that the freeze system detect the disconnection.\n"); login_log("Connexion of the char-server '%s' REFUSED - already connected (account: %ld-%s, pass: %s, ip: %s)" RETCODE, server_name, account.account_id, account.userid, account.passwd, ip); - login_log("You must probably wait that the freeze system detect the disconnection." RETCODE); } else { printf("Connection of the char-server '%s' REFUSED (account: %s, pass: %s, ip: %s).\n", server_name, account.userid, account.passwd, ip); login_log("Connexion of the char-server '%s' REFUSED (account: %s, pass: %s, ip: %s)" RETCODE, @@ -3086,12 +3128,12 @@ int parse_login(int fd) { if (!check_ladminip(session[fd]->client_addr.sin_addr.s_addr)) { login_log("'ladmin'-login: Connection in administration mode refused: IP isn't authorised (ladmin_allow, ip: %s)." RETCODE, ip); } else { - struct login_session_data *ld = session[fd]->session_data; + struct login_session_data *ld = (struct login_session_data*)session[fd]->session_data; if (RFIFOW(fd,2) == 0) { // non encrypted password - unsigned char* password=""; + char* password=""; memcpy(password, RFIFOP(fd,4), 24); password[24] = '\0'; - remove_control_chars(password); + remove_control_chars((unsigned char *)password); // If remote administration is enabled and password sent by client matches password read from login server configuration file if ((admin_state == 1) && (strcmp(password, admin_pass) == 0)) { login_log("'ladmin'-login: Connection in administration mode accepted (non encrypted password: %s, ip: %s)" RETCODE, password, ip); @@ -3138,7 +3180,7 @@ int parse_login(int fd) { logfp = fopen(login_log_unknown_packets_filename, "a"); if (logfp) { gettimeofday(&tv, NULL); - strftime(tmpstr, 23, date_format, localtime(&(tv.tv_sec))); + strftime(tmpstr, 23, date_format, localtime((const time_t*)&(tv.tv_sec))); fprintf(logfp, "%s.%03d: receiving of an unknown packet -> disconnection" RETCODE, tmpstr, (int)tv.tv_usec / 1000); fprintf(logfp, "parse_login: connection #%d (ip: %s), packet: 0x%x (with being read: %d)." RETCODE, fd, ip, RFIFOW(fd,0), RFIFOREST(fd)); fprintf(logfp, "Detail (in hex):" RETCODE); @@ -3186,9 +3228,9 @@ int parse_console(char *buf) { char command[256]; memset(command,0,sizeof(command)); - + sscanf(buf, "%[^\n]", command); - + login_log("Console command :%s" RETCODE, command); if(strcmpi("shutdown", command) == 0 || @@ -3260,8 +3302,8 @@ int login_lan_config_read(const char *lancfgName) { if (sscanf(line,"%[^:]: %[^\r\n]", w1, w2) != 2) continue; - remove_control_chars(w1); - remove_control_chars(w2); + remove_control_chars((unsigned char *)w1); + remove_control_chars((unsigned char *)w2); if (strcmpi(w1, "lan_char_ip") == 0) { // Read Char-Server Lan IP Address memset(lan_char_ip, 0, sizeof(lan_char_ip)); h = gethostbyname(w2); @@ -3328,6 +3370,9 @@ int login_lan_config_read(const char *lancfgName) { int login_config_read(const char *cfgName) { char line[1024], w1[1024], w2[1024]; FILE *fp; + struct hostent *h = NULL; + + bind_ip_str[0] = '\0'; if ((fp = fopen(cfgName, "r")) == NULL) { printf("Configuration file (%s) not found.\n", cfgName); @@ -3342,8 +3387,8 @@ int login_config_read(const char *cfgName) { line[sizeof(line)-1] = '\0'; memset(w2, 0, sizeof(w2)); if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) { - remove_control_chars(w1); - remove_control_chars(w2); + remove_control_chars((unsigned char *)w1); + remove_control_chars((unsigned char *)w2); if (strcmpi(w1, "admin_state") == 0) { admin_state = config_switch(w2); @@ -3353,22 +3398,22 @@ int login_config_read(const char *cfgName) { admin_pass[sizeof(admin_pass)-1] = '\0'; } else if (strcmpi(w1, "ladminallowip") == 0) { if (strcmpi(w2, "clear") == 0) { - if (access_ladmin_allow) - free(access_ladmin_allow); + if (access_ladmin_allow) + aFree(access_ladmin_allow); access_ladmin_allow = NULL; access_ladmin_allownum = 0; } else { if (strcmpi(w2, "all") == 0) { // reset all previous values if (access_ladmin_allow) - free(access_ladmin_allow); + aFree(access_ladmin_allow); // set to all access_ladmin_allow = (char*)aCalloc(ACO_STRSIZE, sizeof(char)); access_ladmin_allownum = 1; access_ladmin_allow[0] = '\0'; } else if (w2[0] && !(access_ladmin_allownum == 1 && access_ladmin_allow[0] == '\0')) { // don't add IP if already 'all' if (access_ladmin_allow) - access_ladmin_allow = realloc(access_ladmin_allow, (access_ladmin_allownum+1) * ACO_STRSIZE); + access_ladmin_allow = (char*)aRealloc(access_ladmin_allow, (access_ladmin_allownum+1) * ACO_STRSIZE); else access_ladmin_allow = (char*)aCalloc(ACO_STRSIZE, sizeof(char)); strncpy(access_ladmin_allow + (access_ladmin_allownum++) * ACO_STRSIZE, w2, ACO_STRSIZE); @@ -3383,6 +3428,14 @@ int login_config_read(const char *cfgName) { level_new_gm = atoi(w2); } else if (strcmpi(w1, "new_account") == 0) { new_account_flag = config_switch(w2); + } else if (strcmpi(w1, "bind_ip") == 0) { + //bind_ip_set_ = 1; + h = gethostbyname (w2); + if (h != NULL) { + printf("Login server binding IP address : %s -> %d.%d.%d.%d\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + sprintf(bind_ip_str, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + } else + memcpy(bind_ip_str,w2,16); } else if (strcmpi(w1, "login_port") == 0) { login_port = atoi(w2); } else if (strcmpi(w1, "account_filename") == 0) { @@ -3401,6 +3454,8 @@ int login_config_read(const char *cfgName) { memset(login_log_filename, 0, sizeof(login_log_filename)); strncpy(login_log_filename, w2, sizeof(login_log_filename)); login_log_filename[sizeof(login_log_filename)-1] = '\0'; + } else if (strcmpi(w1, "log_login") == 0) { + log_login = atoi(w2); } else if (strcmpi(w1, "login_log_unknown_packets_filename") == 0) { memset(login_log_unknown_packets_filename, 0, sizeof(login_log_unknown_packets_filename)); strncpy(login_log_unknown_packets_filename, w2, sizeof(login_log_unknown_packets_filename)); @@ -3448,21 +3503,21 @@ int login_config_read(const char *cfgName) { } else if (strcmpi(w1, "allow") == 0) { if (strcmpi(w2, "clear") == 0) { if (access_allow) - free(access_allow); + aFree(access_allow); access_allow = NULL; access_allownum = 0; } else { if (strcmpi(w2, "all") == 0) { // reset all previous values if (access_allow) - free(access_allow); + aFree(access_allow); // set to all access_allow = (char*)aCalloc(ACO_STRSIZE, sizeof(char)); access_allownum = 1; access_allow[0] = '\0'; } else if (w2[0] && !(access_allownum == 1 && access_allow[0] == '\0')) { // don't add IP if already 'all' if (access_allow) - access_allow = realloc(access_allow, (access_allownum+1) * ACO_STRSIZE); + access_allow = (char*)aRealloc(access_allow, (access_allownum+1) * ACO_STRSIZE); else access_allow = (char*)aCalloc(ACO_STRSIZE, sizeof(char)); strncpy(access_allow + (access_allownum++) * ACO_STRSIZE, w2, ACO_STRSIZE); @@ -3472,21 +3527,21 @@ int login_config_read(const char *cfgName) { } else if (strcmpi(w1, "deny") == 0) { if (strcmpi(w2, "clear") == 0) { if (access_deny) - free(access_deny); + aFree(access_deny); access_deny = NULL; access_denynum = 0; } else { if (strcmpi(w2, "all") == 0) { // reset all previous values if (access_deny) - free(access_deny); + aFree(access_deny); // set to all access_deny = (char*)aCalloc(ACO_STRSIZE, sizeof(char)); access_denynum = 1; access_deny[0] = '\0'; } else if (w2[0] && !(access_denynum == 1 && access_deny[0] == '\0')) { // don't add IP if already 'all' if (access_deny) - access_deny = realloc(access_deny, (access_denynum+1) * ACO_STRSIZE); + access_deny = (char*)aRealloc(access_deny, (access_denynum+1) * ACO_STRSIZE); else access_deny = (char*)aCalloc(ACO_STRSIZE, sizeof(char)); strncpy(access_deny + (access_denynum++) * ACO_STRSIZE, w2, ACO_STRSIZE); @@ -3502,13 +3557,6 @@ int login_config_read(const char *cfgName) { dynamic_pass_failure_ban_how_many = atoi(w2); } else if (strcmpi(w1, "dynamic_pass_failure_ban_how_long") == 0) { dynamic_pass_failure_ban_how_long = atoi(w2); - // Anti-Freeze - } else if(strcmpi(w1,"anti_freeze_enable")==0){ - anti_freeze_enable = config_switch(w2); - } else if (strcmpi(w1, "anti_freeze_interval") == 0) { - ANTI_FREEZE_INTERVAL = atoi(w2); - if (ANTI_FREEZE_INTERVAL < 5) - ANTI_FREEZE_INTERVAL = 5; // minimum 5 seconds } else if (strcmpi(w1, "import") == 0) { login_config_read(w2); } else if(strcmpi(w1,"imalive_on")==0) { //Added by Mugendai for I'm Alive mod @@ -3519,6 +3567,15 @@ int login_config_read(const char *cfgName) { flush_on = atoi(w2); //Added by Mugendai for GUI } else if(strcmpi(w1,"flush_time")==0) { //Added by Mugendai for GUI flush_time = atoi(w2); //Added by Mugendai for GUI + } else if(strcmpi(w1, "check_client_version") == 0){ //Added by Sirius for client version check + if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 ){ + check_client_version = 1; + } + if(strcmpi(w2,"off") == 0 || strcmpi(w2,"no") == 0 ){ + check_client_version = 0; + } + }else if(strcmpi(w1, "client_version_to_connect") == 0){ //Added by Sirius for client version check + client_version_to_connect = atoi(w2); //Added by Sirius for client version check } else if (strcmpi(w1, "console") == 0) { if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 ) console = 1; @@ -3850,32 +3907,42 @@ int flush_timer(int tid, unsigned int tick, int id, int data){ //-------------------------------------- // Function called at exit of the server //-------------------------------------- +static int online_db_final(void *key,void *data,va_list ap) +{ + int *p = (int *) data; + if (p) aFree(p); + return 0; +} void do_final(void) { int i, fd; - + printf("Terminating...\n"); + fflush(stdout); mmo_auth_sync(); + numdb_final(online_db, online_db_final); - if(auth_dat) free(auth_dat); - if(gm_account_db) free(gm_account_db); - if(access_ladmin_allow) free(access_ladmin_allow); - if(access_allow) free(access_allow); - if(access_deny) free(access_deny); + if(auth_dat) aFree(auth_dat); + if(gm_account_db) aFree(gm_account_db); + if(access_ladmin_allow) aFree(access_ladmin_allow); + if(access_allow) aFree(access_allow); + if(access_deny) aFree(access_deny); for (i = 0; i < MAX_SERVERS; i++) { if ((fd = server_fd[i]) >= 0) { server_fd[i] = -1; memset(&server[i], 0, sizeof(struct mmo_char_server)); close(fd); delete_session(fd); - if(session[fd]->session_data) free(session[fd]->session_data); } } close(login_fd); delete_session(login_fd); + exit_dbn(); + timer_final(); login_log("----End of login-server (normal end with closing of all files)." RETCODE); if(log_fp) fclose(log_fp); + printf("Finished.\n"); } //------------------------------ @@ -3884,6 +3951,7 @@ void do_final(void) { int do_init(int argc, char **argv) { int i, j; + SERVER_TYPE = SERVER_LOGIN; // read login-server configuration login_config_read((argc > 1) ? argv[1] : LOGIN_CONF_NAME); display_conf_warnings(); // not in login_config_read, because we can use 'import' option, and display same message twice or more @@ -3905,12 +3973,17 @@ int do_init(int argc, char **argv) { read_gm_account(); // set_termfunc(mmo_auth_sync); set_defaultparse(parse_login); - login_fd = make_listen_port(login_port); - - if(anti_freeze_enable > 0) { - add_timer_func_list(char_anti_freeze_system, "char_anti_freeze_system"); - i = add_timer_interval(gettick() + 1000, char_anti_freeze_system, 0, 0, ANTI_FREEZE_INTERVAL * 1000); - } + // Online user database init + online_db = numdb_init(); + + if (bind_ip_str[0] != '\0') + bind_ip = inet_addr(bind_ip_str); + else + bind_ip = INADDR_ANY; + + //login_fd = make_listen_port(login_port); + login_fd = make_listen_bind(bind_ip,login_port); + add_timer_func_list(check_auth_sync, "check_auth_sync"); i = add_timer_interval(gettick() + 60000, check_auth_sync, 0, 0, 60000); // every 60 sec we check if we must save accounts file (only if necessary to save) @@ -3934,7 +4007,7 @@ int do_init(int argc, char **argv) { set_defaultconsoleparse(parse_console); start_console(); } - + login_log("The login-server is ready (Server is listening on the port %d)." RETCODE, login_port); printf("The login-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n", login_port); diff --git a/src/login/login.h b/src/login/login.h index 9ae4734fe..c08952383 100644 --- a/src/login/login.h +++ b/src/login/login.h @@ -13,8 +13,9 @@ #define START_ACCOUNT_NUM 2000000 #define END_ACCOUNT_NUM 100000000 -int login_port; +extern int login_port; struct mmo_account { + int version; //Added for version check [Sirius] char* userid; char passwd[33]; int passwdenc; @@ -33,9 +34,9 @@ struct mmo_char_server { short port; int users; int maintenance; - int new; + int new_; }; -struct mmo_char_server server[MAX_SERVERS]; -int server_fd[MAX_SERVERS]; +extern struct mmo_char_server server[MAX_SERVERS]; +extern int server_fd[MAX_SERVERS]; #endif diff --git a/src/login/md5calc.c b/src/login/md5calc.c index 96bfc34d0..0ee64476d 100644 --- a/src/login/md5calc.c +++ b/src/login/md5calc.c @@ -96,7 +96,7 @@ static void MD5_Round_Calculate(const unsigned char *block, //Save A as AA, B as BB, C as CC, and and D as DD (saving of A, B, C, and D) unsigned int A=*A2, B=*B2, C=*C2, D=*D2; unsigned int AA = A,BB = B,CC = C,DD = D; - + //It is a large region variable reluctantly because of calculation of a round. . . for Round1...4 pX = X; @@ -187,7 +187,7 @@ void MD5_String2binary(const char * string, char * output) memset(padding_message+copy_len, 0, 64 - copy_len); //It buries by 0 until it becomes extended bit length. padding_message[copy_len] |= 0x80; //The next of a message is 1. - //1-4 + //1-4 //If 56 bytes or more (less than 64 bytes) of remainder becomes, it will calculate by extending to 64 bytes. if (56 <= copy_len) { MD5_Round_Calculate(padding_message, A,B,C,D); @@ -226,7 +226,7 @@ void MD5_String(const char * string, char * output) { unsigned char digest[16]; - MD5_String2binary(string,digest); + MD5_String2binary(string,(char*)digest); sprintf(output, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", digest[ 0], digest[ 1], digest[ 2], digest[ 3], diff --git a/src/login_sql/GNUmakefile b/src/login_sql/GNUmakefile deleted file mode 100644 index e941469e1..000000000 --- a/src/login_sql/GNUmakefile +++ /dev/null @@ -1,18 +0,0 @@ -all: login-server_sql -sql: login-server_sql - -shared_libs=all -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o ../common/nullpo.o -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/nullpo.h - -login-server_sql: login.o char_int.o login_int.o md5calc.o strlib.o $(COMMON_OBJ) - $(CC) -o ../../$@ $^ $(LIB_S) - -login.o: login.c login.h md5calc.h strlib.h char_int.h login_int.h $(COMMON_H) -char_int.o: char_int.c login.h char_int.h $(COMMON_H) -login_int.o: login_int.c login.h login_int.h char_int.h $(COMMON_H) -md5calc.o: md5calc.c md5calc.h -strlib.o: strlib.c strlib.h - -clean: - rm -f *.o ../../login-server_sql
\ No newline at end of file diff --git a/src/login_sql/Makefile b/src/login_sql/Makefile index e941469e1..20b01c66d 100644 --- a/src/login_sql/Makefile +++ b/src/login_sql/Makefile @@ -2,17 +2,15 @@ all: login-server_sql sql: login-server_sql shared_libs=all -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o ../common/nullpo.o -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/nullpo.h +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o +COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h -login-server_sql: login.o char_int.o login_int.o md5calc.o strlib.o $(COMMON_OBJ) +login-server_sql: login.o md5calc.o $(COMMON_OBJ) $(CC) -o ../../$@ $^ $(LIB_S) -login.o: login.c login.h md5calc.h strlib.h char_int.h login_int.h $(COMMON_H) -char_int.o: char_int.c login.h char_int.h $(COMMON_H) -login_int.o: login_int.c login.h login_int.h char_int.h $(COMMON_H) +login.o: login.c login.h md5calc.h $(COMMON_H) md5calc.o: md5calc.c md5calc.h -strlib.o: strlib.c strlib.h clean: - rm -f *.o ../../login-server_sql
\ No newline at end of file + rm -f *.o ../../login-server_sql + diff --git a/src/login_sql/char_int.c b/src/login_sql/char_int.c deleted file mode 100644 index 30153737a..000000000 --- a/src/login_sql/char_int.c +++ /dev/null @@ -1,512 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <time.h> -#include <signal.h> -#include <fcntl.h> -#include <string.h> - -#include "login.h" - -//-------------------------------- -// Send to char -//-------------------------------- -int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) { - int i, c; - int fd; - - c = 0; - for(i = 0; i < MAX_SERVERS && i < servers_connected; i++) { - if ((fd = server_fd[i]) > 0 && fd != sfd) { - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - c++; - } - } - - return c; -} - -//-------------------------------- -// Char-server anti-freeze system -//-------------------------------- -int char_anti_freeze_system(int tid, unsigned int tick, int id, int data) { - int i; - - for(i = 0; i < MAX_SERVERS && i < servers_connected; i++) { - if (server_fd[i] >= 0) {// if char-server is online -// printf("char_anti_freeze_system: server #%d '%s', flag: %d.\n", i, server[i].name, server_freezeflag[i]); - if (server_freezeflag[i]-- < 1) {// Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed - session[server_fd[i]]->eof = 1; - } - } - } - - return 0; -} - -//------------------------------------------- -// Request for account reg from char-server [Edit: Wizputer] -//------------------------------------------- -int send_account_reg(int fd, int len) { - if (RFIFOREST(fd) < 19) - return -1; - - int account_id = RFIFOL(fd,2); - int i; - - for(i=0;i<AUTH_FIFO_SIZE;i++){ - if (auth_fifo[i].account_id == account_id && - auth_fifo[i].login_id1 == RFIFOL(fd,6) && -#if CMP_AUTHFIFO_LOGIN2 != 0 - auth_fifo[i].login_id2 == RFIFOL(fd,10) && // relate to the versions higher than 18 -#endif - auth_fifo[i].sex == RFIFOB(fd,14) && -#if CMP_AUTHFIFO_IP != 0 - auth_fifo[i].ip == RFIFOL(fd,15) && -#endif - !auth_fifo[i].delflag) { - auth_fifo[i].delflag = 1; - #ifdef DEBUG - printf("Client: [%d] Auth Number: [%d]\n",fd, i); - #endif - break; - } - } - - if (i != AUTH_FIFO_SIZE) { // send account_reg - int p; - time_t connect_until_time = 0; - char email[40] = ""; - - sprintf(tmpsql, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id); - sql_query(tmpsql,"send_account_reg"); - - - if ((sql_res = mysql_store_result(&mysql_handle))) { - if((sql_row = mysql_fetch_row(sql_res))) { - connect_until_time = atol(sql_row[1]); - strcpy(email, sql_row[0]); - } - } - mysql_free_result(sql_res); - - if (account_id > 0) { - sprintf(tmpsql, "SELECT `str`,`value` FROM `global_reg_value` WHERE `type`='1' AND `account_id`='%d'",account_id); - sql_query(tmpsql,"send_account_reg"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { - WFIFOW(fd,0) = 0x2729; - WFIFOL(fd,4) = account_id; - for(p = 8; (sql_row = mysql_fetch_row(sql_res));p+=36){ - memcpy(WFIFOP(fd,p), sql_row[0], 32); - WFIFOL(fd,p+32) = atoi(sql_row[1]); - } - WFIFOW(fd,2) = p; - WFIFOSET(fd,p); - #ifdef DEBUG - printf("account_reg2 send : login->char (auth fifo)\n"); - #endif - WFIFOW(fd,0) = 0x2713; - WFIFOL(fd,2) = account_id; - WFIFOB(fd,6) = 0; - memcpy(WFIFOP(fd, 7), email, 40); - WFIFOL(fd,47) = (unsigned long) connect_until_time; - WFIFOSET(fd,51); - } - mysql_free_result(sql_res); - } - } else { - WFIFOW(fd,0) = 0x2713; - WFIFOL(fd,2) = account_id; - WFIFOB(fd,6) = 1; - WFIFOSET(fd,51); - } - RFIFOSKIP(fd,19); - - return 0; -} - -//---------------------------------------------------------- -// Number of users in the world (connected char-server(s)) [Edit: Wizputer] -//---------------------------------------------------------- -int number_world_users(int fd, int len, int id) { - if (len < 6) - return -1; - - #ifdef DEBUG - if (server[id].users != RFIFOL(fd,2)) - printf("set number users %s : %d\n", server[id].name, RFIFOL(fd,2)); - #endif - - server[id].users = RFIFOL(fd,2); - if(anti_freeze_enable) - server_freezeflag[id] = 5; // Char anti-freeze system. Counter. 5 ok, 4...0 freezed - - sprintf(tmpsql,"UPDATE `sstatus` SET `user` = '%d' WHERE `index` = '%d'", server[id].users, id); - sql_query(tmpsql,"number_world_users"); - - RFIFOSKIP(fd,6); - - return 0; -} - -//----------------------------------------- -// Email and Time request from char-server [Edit: Wizputer] -//----------------------------------------- -int email_time_request(int fd, int len, int id) { - if (len < 6) - return -1; - - int account_id=RFIFOL(fd,2); - time_t connect_until_time = 0; - char email[40] = ""; - - sprintf(tmpsql,"SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'",login_db, login_db_account_id, account_id); - sql_query(tmpsql,"email_time_request"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { - if((sql_row = mysql_fetch_row(sql_res))) { - connect_until_time = atol(sql_row[1]); - strcpy(email, sql_row[0]); - } - } - mysql_free_result(sql_res); - - #ifdef DEBUG - printf("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, account_id); - #endif - - WFIFOW(fd,0) = 0x2717; - WFIFOL(fd,2) = account_id; - memcpy(WFIFOP(fd, 6), email, 40); - WFIFOL(fd,46) = (unsigned long) connect_until_time; - WFIFOSET(fd,50); - - RFIFOSKIP(fd,6); - - return 0; -} - -//-------------------------------- -// Request to change email [Edit: Wizputer] -//-------------------------------- -int change_account_email(int fd, int len, int id, char ip[16]) { - if (len < 86) - return -1; - - int acc = RFIFOL(fd,2); - char actual_email[40], new_email[40]; - - memcpy(actual_email, RFIFOP(fd,6), 40); - memcpy(new_email, RFIFOP(fd,46), 40); - - if (e_mail_check(actual_email) == 0) { - #ifdef DEBUG - printf("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)" RETCODE, - server[id].name, acc, ip); - #endif - } else if (e_mail_check(new_email) == 0) { - #ifdef DEBUG - printf("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)" RETCODE, - server[id].name, acc, ip); - #endif - } else if (strcmpi(new_email, "athena@athena.com") == 0) { - #ifdef DEBUG - printf("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)" RETCODE, - server[id].name, acc, ip); - #endif - } else { - sprintf(tmpsql, "SELECT `%s`,`email` FROM `%s` WHERE `%s` = '%d'", login_db_userid, login_db, login_db_account_id, acc); - sql_query(tmpsql,"change_account_email"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { - if((sql_row = mysql_fetch_row(sql_res))) { //row fetching - if (strcmpi(sql_row[1], actual_email) == 0) { - sprintf(tmpsql, "UPDATE `%s` SET `email` = '%s' WHERE `%s` = '%d'", login_db, new_email, login_db_account_id, acc); - sql_query(tmpsql,"change_account_email"); - - #ifdef DEBUG - printf("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s)." RETCODE, - server[id].name, acc, sql_row[0], actual_email, ip); - #endif - } - } - } - - } - - RFIFOSKIP(fd, 86); - - return 0; -} - -//----------------------------------------------- -// State change request from map server (By Yor) [Edit: Wizputer] -//----------------------------------------------- -int status_change_request(int fd, int len) { - if (len < 10) - return -1; - - int acc = RFIFOL(fd,2), status = RFIFOL(fd,6); - - sprintf(tmpsql, "SELECT `state` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, acc); - sql_query(tmpsql,"status_change_request"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { - if((sql_row = mysql_fetch_row(sql_res))) { // row fetching - if (atoi(sql_row[0]) != status && status != 0) { - unsigned char buf[16]; - WBUFW(buf,0) = 0x2731; - WBUFL(buf,2) = acc; - WBUFB(buf,6) = 0; // 0: change of statut, 1: ban - WBUFL(buf,7) = status; // status or final date of a banishment - charif_sendallwos(-1, buf, 11); - } - } - - sprintf(tmpsql,"UPDATE `%s` SET `state` = '%d' WHERE `%s` = '%d'", login_db, status,login_db_account_id,acc); - sql_query(tmpsql,"status_change_request"); - } - - RFIFOSKIP(fd,10); - - return 0; -} -//-------------------------------------- -// Ban request from map-server (By Yor) [Edit: Wizputer] -//-------------------------------------- -int ban_request(int fd, int len) { - if (len < 18) - return -1; - - int acc=RFIFOL(fd,2); - struct tm *tmtime; - time_t timestamp, tmptime; - - sprintf(tmpsql, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc); - sql_query(tmpsql,"ban_request"); - - if ((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) { - tmptime = atol(sql_row[0]); - - if (tmptime == 0 || tmptime < time(NULL)) - timestamp = time(NULL); - else - timestamp = tmptime; - - tmtime = localtime(×tamp); - tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,6); - tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,8); - tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,10); - tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,12); - tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,14); - tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,16); - - timestamp = mktime(tmtime); - - if (timestamp != -1) { - if (timestamp <= time(NULL)) - timestamp = 0; - if (tmptime != timestamp) { - if (timestamp != 0) { - unsigned char buf[16]; - WBUFW(buf,0) = 0x2731; - WBUFL(buf,2) = acc; - WBUFB(buf,6) = 1; // 0: change of statut, 1: ban - WBUFL(buf,7) = timestamp; // status or final date of a banishment - charif_sendallwos(-1, buf, 11); - } - #ifdef DEBUG - printf("Account: [%d] Banned until: [%ld]\n", acc, timestamp); - #endif - - sprintf(tmpsql, "UPDATE `%s` SET `ban_until` = '%ld', `state`='7' WHERE `%s` = '%d'", login_db, timestamp, login_db_account_id, acc); - sql_query(tmpsql,"ban_request"); - } - } - } - - RFIFOSKIP(fd,18); - - return 0; -} - -//----------------------------- -// Change sex [Edit: Wizputer] -//----------------------------- -int change_sex(int fd,int len) { - if (len < 6) - return -1; - - int sex,acc=RFIFOL(fd,4); - unsigned char buf[16]; - - sprintf(tmpsql,"SELECT `sex` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc); - sql_query(tmpsql,"change_sex"); - - if ((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) { - if (strcmpi(sql_row[0], "M") == 0) - sex = 1; - else - sex = 0; - - sprintf(tmpsql,"UPDATE `%s` SET `sex` = '%c' WHERE `%s` = '%d'", login_db, (sex==0?'M':'F'), login_db_account_id, acc); - sql_query(tmpsql,"change_sex"); - - WBUFW(buf,0) = 0x2723; - WBUFL(buf,2) = acc; - WBUFB(buf,6) = sex; - charif_sendallwos(-1, buf, 7); - } - - RFIFOSKIP(fd,6); - - return 0; -} - -//------------------------------- -// Save Account Reg [Edit: Wizputer] -//------------------------------- -int save_account_reg(int fd, int len){ - if (len < 4 || len < RFIFOW(fd,2)) - return -1; - - int p,j,value,acc=RFIFOL(fd,4); - char str[32]; - char temp_str[32]; - - if (acc>0){ - unsigned char buf[RFIFOW(fd,2)+1]; - for(p=8,j=0;p<RFIFOW(fd,2) && j<ACCOUNT_REG2_NUM;p+=36,j++){ - memcpy(str,RFIFOP(fd,p),32); - value=RFIFOL(fd,p+32); - - sprintf(tmpsql,"REPLACE INTO `global_reg_value` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , '%s' , '%d');", acc, jstrescapecpy(temp_str,str), value); - sql_query(tmpsql,"save_account_reg"); - } - - // Send to char - memcpy(WBUFP(buf,0),RFIFOP(fd,0),RFIFOW(fd,2)); - WBUFW(buf,0)=0x2729; - charif_sendallwos(fd,buf,WBUFW(buf,2)); - } - - RFIFOSKIP(fd,RFIFOW(fd,2)); - - #ifdef DEBUG - printf("login: save account_reg (from char)\n"); - #endif - - return 0; -} - -//------------------------------------------------ -// Recieve unban request from map-server (by Yor) [Edit: Wizputer] -//------------------------------------------------ -int unban_request(int fd, int len) { - if (len < 6) - return -1; - - int acc = RFIFOL(fd,2); - - sprintf(tmpsql,"UPDATE `%s` SET `ban_until` = '0', `state`='0' WHERE `%s` = '%d' AND `state`='6'", login_db,login_db_account_id,acc); - sql_query(tmpsql,"unban_request"); - - RFIFOSKIP(fd,6); - - return 0; -} - -//--------------------------------------- -// Map-server Add Online User [Wizputer] -//--------------------------------------- -int map_add_online_user(int fd, int len) { - if (len < 6) - return -1; - - add_online_user(RFIFOL(fd,2)); - - RFIFOSKIP(fd,6); - - return 0; -} - -//--------------------------------------- -// Map-server Remove Online User [Wizputer] -//--------------------------------------- -int map_rem_online_user(int fd, int len) { - if (len < 6) - return -1; - - remove_online_user(RFIFOL(fd,2)); - - RFIFOSKIP(fd,6); - - return 0; -} - -//----------------------------------------------------- -// char-server packet parse [Edit: Wizputer] -//----------------------------------------------------- -int parse_fromchar(int fd){ - int id, len, res=0; - - unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr; - char ip[16]; - - sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - - for(id = 0; id < MAX_SERVERS && id < servers_connected; id++) - if (server_fd[id] == fd) - break; - - if (id == MAX_SERVERS) - session[fd]->eof = 1; - - if(session[fd]->eof) { - if (id < MAX_SERVERS) { - printf("Char-server '%s' has disconnected.\n", server[id].name); - server_fd[id] = -1; - memset(&server[id], 0, sizeof(struct mmo_char_server)); - servers_connected--; - // server delete - sprintf(tmpsql, "DELETE FROM `sstatus` WHERE `index`='%d'", id); - sql_query(tmpsql,"parse_fromchar"); - } - close(fd); - delete_session(fd); - return 0; - } - - len = RFIFOREST(fd); - - while(len >= 2 && res == 0) { - #ifdef DEBUG_PACKETS - printf("char_parse: %d %d packet case=%x\n", fd, RFIFOREST(fd), RFIFOW(fd, 0)); - #endif - - switch (RFIFOW(fd,0)) { - case 0x2712: res = send_account_reg(fd,len); break; - case 0x2714: res = number_world_users(fd,len,id); break; - case 0x2716: res = email_time_request(fd,len,id); break; - case 0x2722: res = change_account_email(fd,len,id,ip); break; - case 0x2724: res = status_change_request(fd,len); break; - case 0x2725: res = ban_request(fd,len); break; - case 0x2727: res = change_sex(fd,len); break; - case 0x2728: res = save_account_reg(fd,len); break; - case 0x272a: res = unban_request(fd,len); break; - case 0x272b: res = map_add_online_user(fd,len); break; - case 0x272c: res = map_rem_online_user(fd,len); break; - - default: - #ifdef DEBUG - printf("login: unknown packet %x! (from char).\n", RFIFOW(fd,0)); - #endif - session[fd]->eof = 1; - } - - len = RFIFOREST(fd); - } - - return 0; -} diff --git a/src/login_sql/char_int.h b/src/login_sql/char_int.h deleted file mode 100644 index 195d1be42..000000000 --- a/src/login_sql/char_int.h +++ /dev/null @@ -1,2 +0,0 @@ -int char_anti_freeze_system(int, unsigned int, int, int); -int parse_fromchar(int); diff --git a/src/login_sql/login.c b/src/login_sql/login.c index 3785d33d8..ff9e4706a 100644 --- a/src/login_sql/login.c +++ b/src/login_sql/login.c @@ -4,18 +4,56 @@ #include <sys/types.h> +#ifdef LCCWIN32 +#include <winsock.h> +#pragma lib <libmysql.lib> +#else +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <winsock2.h> +#include <time.h> +void Gettimeofday(struct timeval *timenow) +{ + time_t t; + t = clock(); + timenow->tv_usec = t; + timenow->tv_sec = t / CLK_TCK; + return; +} +#define gettimeofday(timenow, dummy) Gettimeofday(timenow) +#pragma comment(lib,"libmysql.lib") +#else +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <unistd.h> +#endif +#endif + #include <stdio.h> #include <stdlib.h> #include <time.h> +#include <sys/stat.h> // for stat/lstat/fstat #include <signal.h> #include <fcntl.h> #include <string.h> -#include "timer.h" - +//add include for DBMS(mysql) +#include <mysql.h> + +#include "../common/core.h" +#include "../common/socket.h" +#include "../common/malloc.h" +#include "../common/db.h" +#include "../common/timer.h" +#include "../common/strlib.h" +#include "../common/mmo.h" +#include "../common/version.h" #include "login.h" -#include "login_int.h" -#include "char_int.h" #ifdef PASSWORDENC #include "md5calc.h" @@ -26,66 +64,42 @@ #endif #define J_MAX_MALLOC_SIZE 65535 -// Login Listening Port -int login_port = 6900; - -struct auth_fifo auth_fifo[AUTH_FIFO_SIZE]; - -int auth_fifo_pos; - -// MySQL Query -char tmpsql[65535], prev_query[65535]; - -// MySQL Connection Handle -MYSQL mysql_handle; -MYSQL_RES* sql_res ; -MYSQL_ROW sql_row ; - -// It's to check IP of a player between login-server and char-server (part of anti-hacking system) -int check_ip_flag; - -// Login's FD -int login_fd; -// LAN IP of char-server and subnet mask(Kashy) -char lan_char_ip[16]; -int subnetmaski[4]; +//----------------------------------------------------- +// global variable +//----------------------------------------------------- +int account_id_count = START_ACCOUNT_NUM; +int server_num; +int new_account_flag = 0; //Set from config too XD [Sirius] +char bind_ip_str[16]; +in_addr_t bind_ip; +int login_port = 6900; +char lan_char_ip[128]; // Lan char ip added by kashy +int subnetmaski[4]; // Subnetmask added by kashy -// Char-server data struct mmo_char_server server[MAX_SERVERS]; int server_fd[MAX_SERVERS]; -unsigned char servers_connected = 0; - -// Anti-freeze Data -int server_freezeflag[MAX_SERVERS]; -int anti_freeze_enable = 0; -int ANTI_FREEZE_INTERVAL = 15; - -// MD5 Key Data for encrypted login -char md5key[20]; -int md5keylen = 16; -// Auth FIFO Position -int auth_fifo_pos = 0; +int login_fd; //Added for Mugendai's I'm Alive mod int imalive_on=0; int imalive_time=60; - //Added by Mugendai for GUI int flush_on=1; int flush_time=100; -// Date format for bans char date_format[32] = "%Y-%m-%d %H:%M:%S"; +int auth_num = 0, auth_max = 0; -// minimum level of player/GM (0: player, 1-99: gm) to connect on the server -int min_level_to_connect = 0; +int min_level_to_connect = 0; // minimum level of player/GM (0: player, 1-99: gm) to connect on the server +int check_ip_flag = 1; // It's to check IP of a player between login-server and char-server (part of anti-hacking system) +int check_client_version = 0; //Client version check ON/OFF .. (sirius) +int client_version_to_connect = 20; //Client version needed to connect ..(sirius) +int register_users_online = 1; -// It's to check IP of a player between login-server and char-server (part of anti-hacking system) -int check_ip_flag = 1; +MYSQL mysql_handle; -// Dynamic IP Ban config int ipban = 1; int dynamic_account_ban = 1; int dynamic_account_ban_class = 0; @@ -94,160 +108,116 @@ int dynamic_pass_failure_ban_time = 5; int dynamic_pass_failure_ban_how_many = 3; int dynamic_pass_failure_ban_how_long = 60; -// MySQL Config int login_server_port = 3306; -char login_server_ip[16] = "127.0.0.1"; -char login_server_id[16] = "ragnarok"; -char login_server_pw[16] = "ragnarok"; -char login_server_db[16] = "ragnarok"; +char login_server_ip[32] = "127.0.0.1"; +char login_server_id[32] = "ragnarok"; +char login_server_pw[32] = "ragnarok"; +char login_server_db[32] = "ragnarok"; int use_md5_passwds = 0; +char login_db[256] = "login"; +char loginlog_db[256] = "loginlog"; + +// added to help out custom login tables, without having to recompile +// source so options are kept in the login_athena.conf or the inter_athena.conf +char login_db_account_id[256] = "account_id"; +char login_db_userid[256] = "userid"; +char login_db_user_pass[256] = "user_pass"; +char login_db_level[256] = "level"; -// MySQL custom table and column names -char login_db[32] = "login"; -char loginlog_db[32] = "loginlog"; -char login_db_account_id[32] = "account_id"; -char login_db_userid[32] = "userid"; -char login_db_user_pass[32] = "user_pass"; -char login_db_level[32] = "level"; +char tmpsql[65535], tmp_sql[65535]; -// Console interface on/off int console = 0; -// Online User DB -struct dbt *online_db; +int case_sensitive = 1; + +//----------------------------------------------------- + +#define AUTH_FIFO_SIZE 256 +struct { + int account_id,login_id1,login_id2; + int ip,sex,delflag; +} auth_fifo[AUTH_FIFO_SIZE]; + +int auth_fifo_pos = 0; -// GM Database -struct dbt *gm_db; -int lowest_gm_level = 1; + +//----------------------------------------------------- + +static char md5key[20], md5keylen = 16; + +struct dbt *online_db; //----------------------------------------------------- // Online User Database [Wizputer] //----------------------------------------------------- void add_online_user(int account_id) { - int *p; - p = malloc(sizeof(int)); - if (p == NULL) { - printf("add_online_user: memory allocation failure (malloc)!\n"); - exit(0); - } - p = &account_id; - numdb_insert(online_db, account_id, p); + int *p; + if(register_users_online <= 0) + return; + p = (int*)aMalloc(sizeof(int)); + *p = account_id; + numdb_insert(online_db, account_id, p); } int is_user_online(int account_id) { - int *p; - - p = numdb_search(online_db, account_id); - if (p == NULL) + int *p; + if(register_users_online <= 0) return 0; - #ifdef DEBUG - printf("Acccount [%d] Online\n",*p); - #endif - return 1; + p = (int*)numdb_search(online_db, account_id); + if (p != NULL) + printf("Acccount %d\n",*p); + + return (p != NULL); } void remove_online_user(int account_id) { - int *p; - p = numdb_erase(online_db,account_id); - free(p); -} - -//---------------------------------------------- -//SQL Commands ( Original by Clownisius ) [Edit: Wizputer] -//---------------------------------------------- - -void sql_query(char* query,char function[32]) { - if(mysql_query(&mysql_handle, query)){ - printf("---------- SQL error report ----------\n"); - printf("MySQL Server Error: %s\n", mysql_error(&mysql_handle)); - printf("Query: %s\n", query); - printf("In function: %s \n", function); - printf("\nPrevious query: %s\n", prev_query); -// if (strcmp(mysql_error(&mysql_handle),"CR_COMMANDS_OUT_OF_SYNC") !=0) printf(" - = Shutting down Char Server = - \n\n"); - printf("-------- End SQL Error Report --------\n"); -// printf("Uncontrolled param: %s",&mysql_handle); -// if (strcmp(mysql_error(&mysql_handle),"CR_COMMANDS_OUT_OF_SYNC") !=0) exit(1); - } - - strcpy(prev_query,query); - + int *p; + if(register_users_online <= 0) + return; + p = (int*)numdb_erase(online_db,account_id); + aFree(p); } //----------------------------------------------------- -// check user level [Wizputer] +// check user level //----------------------------------------------------- -unsigned char isGM(int account_id) { - unsigned char *level; - - level = numdb_search(gm_db, account_id); - if (level == NULL) - return 0; - - return *level; -} - -static int gmdb_final(void *key,void *data,va_list ap) { - unsigned char *level; - - nullpo_retr(0, level=data); - - free(level); - - return 0; -} +int isGM(int account_id) { + int level; -void do_final_gmdb(void) { - if(gm_db){ - numdb_final(gm_db,gmdb_final); - gm_db=NULL; + MYSQL_RES* sql_res; + MYSQL_ROW sql_row; + level = 0; + sprintf(tmpsql,"SELECT `%s` FROM `%s` WHERE `%s`='%d'", login_db_level, login_db, login_db_account_id, account_id); + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error (select GM Level to Memory)- %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); + level = atoi(sql_row[0]); + if (level > 99) + level = 99; } -} - -void read_GMs(int fd) { - unsigned char *level; - int i=0; - - if(gm_db) - do_final_gmdb(); - - gm_db = numdb_init(); - - sprintf(tmpsql,"SELECT `%s`,`%s` FROM `%s` WHERE `%s` > '%d'", login_db_account_id, login_db_level, login_db,login_db_level,lowest_gm_level); - sql_query(tmpsql,"read_GMs"); - - WFIFOW(fd, 0) = 0x2732; - - if ((sql_res = mysql_store_result(&mysql_handle))) { - for(i=0;(sql_row = mysql_fetch_row(sql_res));i++) { - level = malloc(sizeof(unsigned char)); - - if( (*level = atoi(sql_row[1])) > 99 ) - *level = 99; - - numdb_insert(gm_db, atoi(sql_row[0]), level); - - WFIFOL(fd,6+5*i) = atoi(sql_row[0]); - WFIFOB(fd,10+5*i) = *level; - } - WFIFOW(fd,2) = i; - } + if (level == 0) { + return 0; + //not GM + } - WFIFOSET(fd,6+5*i); + mysql_free_result(sql_res); - mysql_free_result(sql_res); + return level; } - //--------------------------------------------------- // E-mail check: return 0 (not correct) or 1 (valid). //--------------------------------------------------- -int e_mail_check(unsigned char *email) { +int e_mail_check(char *email) { char ch; - unsigned char* last_arobas; + char* last_arobas; // athena limits if (strlen(email) < 3 || strlen(email) > 39) @@ -282,56 +252,69 @@ int e_mail_check(unsigned char *email) { } //----------------------------------------------------- -// Connect to MySQL +// Read Account database - mysql db //----------------------------------------------------- int mmo_auth_sqldb_init(void) { - printf("Login-server starting...\n"); + printf("Login server init....\n"); // memory initialize - #ifdef DEBUG printf("memory initialize....\n"); - #endif mysql_init(&mysql_handle); // DB connection start - printf("Connecting to Login Database Server...\n"); + printf("Connect Login Database Server....\n"); if (!mysql_real_connect(&mysql_handle, login_server_ip, login_server_id, login_server_pw, login_server_db, login_server_port, (char *)NULL, 0)) { // pointer check printf("%s\n", mysql_error(&mysql_handle)); exit(1); } else { - printf("Connected to MySQL Server\n"); + printf("connect success!\n"); } - //delete all server status - sprintf(tmpsql,"TRUNCATE TABLE `sstatus`"); - sql_query(tmpsql,"mmo_db_close"); - sprintf(tmpsql, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '', 'lserver', '100','login server started')", loginlog_db); - sql_query(tmpsql,"mmo_auth_sqldb_init"); + + //query + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } return 0; } //----------------------------------------------------- -// Close MySQL and Close all sessions +// DB server connect check +//----------------------------------------------------- +void mmo_auth_sqldb_sync(void) { + // db connect check? or close? + // ping pong DB server -if losted? then connect try. else crash. +} + +//----------------------------------------------------- +// close DB //----------------------------------------------------- void mmo_db_close(void) { int i, fd; //set log. sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '', 'lserver','100', 'login server shutdown')", loginlog_db); - sql_query(tmpsql,"mmo_db_close"); + + //query + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } //delete all server status - sprintf(tmpsql,"TRUNCATE TABLE `sstatus`"); - sql_query(tmpsql,"mmo_db_close"); + sprintf(tmpsql,"DELETE FROM `sstatus`"); + //query + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } mysql_close(&mysql_handle); - printf("MySQL Connection closed\n"); + printf("close DB connect....\n"); for (i = 0; i < MAX_SERVERS; i++) { if ((fd = server_fd[i]) >= 0) @@ -341,96 +324,274 @@ void mmo_db_close(void) { } //----------------------------------------------------- -// Auth account +// Make new account +//----------------------------------------------------- +int mmo_auth_sqldb_new(struct mmo_account* account,const char *tmpstr, char sex) { + //no need on DB version + + printf("Request new account.... - not support on this version\n"); + + return 0; +} + +//----------------------------------------------------- +// Make new account +//----------------------------------------------------- +int mmo_auth_new(struct mmo_account* account, const char *tmpstr, char sex) { + + return 0; +} + +#ifdef LCCWIN32 +extern void gettimeofday(struct timeval *t, struct timezone *dummy); +#endif + +//----------------------------------------------------- +// Auth //----------------------------------------------------- int mmo_auth( struct mmo_account* account , int fd){ struct timeval tv; + time_t ban_until_time; char tmpstr[256]; - char t_uid[32], t_pass[32]; - char user_password[32]; + char t_uid[256], t_pass[256]; + char user_password[256]; - char ip[16]; + //added for account creation _M _F + int len; - int encpasswdok = 0; - int state; + MYSQL_RES* sql_res; + MYSQL_ROW sql_row; + //int sql_fields, sql_cnt; + char md5str[64], md5bin[32]; - #ifdef PASSWORDENC - char logbuf[1024], *p = logbuf; - char md5str[64],md5bin[32]; - int j; - #endif + char ip[16]; unsigned char *sin_addr = (unsigned char *)&session[fd]->client_addr.sin_addr; - sprintf(ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]); - #ifdef DEBUG - printf ("Starting auth for [%s]...\n",ip); - #endif - // auth start : time seed + printf ("auth start...\n"); + sprintf(ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]); + + //accountreg with _M/_F .. [Sirius] + len = strlen(account->userid) -2; + + if (account->passwdenc == 0 && account->userid[len] == '_' && + (account->userid[len+1] == 'F' || account->userid[len+1] == 'M') && new_account_flag == 1 && + account_id_count <= END_ACCOUNT_NUM && len >= 4 && strlen(account->passwd) >= 4) { + if (new_account_flag == 1) + account->userid[len] = '\0'; + sprintf(tmp_sql, "SELECT `%s` FROM `%s` WHERE `userid` = '%s'", login_db_userid, login_db, account->userid); + if(mysql_query(&mysql_handle, tmp_sql)){ + printf("SQL error (_M/_F reg): %s", mysql_error(&mysql_handle)); + }else{ + sql_res = mysql_store_result(&mysql_handle); + if(mysql_num_rows(sql_res) == 0){ + //ok no existing acc, + printf("Adding a new account user: %s with passwd: %s sex: %c (ip: %s)\n", account->userid, account->passwd, account->userid[len+1], ip); + sprintf(tmp_sql, "INSERT INTO `%s` (`%s`, `%s`, `sex`, `email`) VALUES ('%s', '%s', '%c', '%s')", login_db, login_db_userid, login_db_user_pass, account->userid, account->passwd, account->userid[len+1], "a@a.com"); + if(mysql_query(&mysql_handle, tmp_sql)){ + //Failed to insert new acc :/ + printf("SQL Error (_M/_F reg) .. insert ..: %s", mysql_error(&mysql_handle)); + }//sql query check to insert + }//rownum check (0!) + mysql_free_result(sql_res); + }//sqlquery + }//all values for NEWaccount ok ? + + + + // auth start : time seed gettimeofday(&tv, NULL); - strftime(tmpstr, 24, "%Y-%m-%d %H:%M:%S",localtime(&(tv.tv_sec))); + strftime(tmpstr, 24, "%Y-%m-%d %H:%M:%S",localtime((const time_t*)&(tv.tv_sec))); sprintf(tmpstr+19, ".%03d", (int)tv.tv_usec/1000); jstrescapecpy(t_uid,account->userid); jstrescapecpy(t_pass, account->passwd); + // make query sprintf(tmpsql, "SELECT `%s`,`%s`,`%s`,`lastlogin`,`logincount`,`sex`,`connect_until`,`last_ip`,`ban_until`,`state`,`%s`" - " FROM `%s` WHERE `%s`='%s'", login_db_account_id, login_db_userid, login_db_user_pass, login_db_level, login_db, login_db_userid, t_uid); + " FROM `%s` WHERE %s `%s`='%s'", login_db_account_id, login_db_userid, login_db_user_pass, login_db_level, login_db, case_sensitive ? "BINARY" : "", login_db_userid, t_uid); //login {0-account_id/1-userid/2-user_pass/3-lastlogin/4-logincount/5-sex/6-connect_untl/7-last_ip/8-ban_until/9-state} - sql_query(tmpsql,"mmo_auth"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { - if(!(sql_row = mysql_fetch_row(sql_res))) { - #ifdef DEBUG - printf ("Auth failed: No Account Time: [%s] Username: [%s] Password: [%s]\n", tmpstr, account->userid, account->passwd); - #endif + // query + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle) ; + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); //row fetching + if (!sql_row) { + //there's no id. + printf ("auth failed no account %s %s %s\n", tmpstr, account->userid, account->passwd); mysql_free_result(sql_res); return 0; } } else { - #ifdef DEBUG - printf("mmo_auth DB result error\n"); - #endif + printf("mmo_auth DB result error ! \n"); return 0; } + + //Client Version check[Sirius] + if(check_client_version == 1 && account->version != 0){ + if(account->version != client_version_to_connect){ + mysql_free_result(sql_res); + return 6; + } + } + + // Documented by CLOWNISIUS || LLRO || Gunstar lead this one with me + // IF changed to diferent returns~ you get diferent responses from your msgstringtable.txt + //Ireturn 2 == line 9 + //Ireturn 5 == line 311 + //Ireturn 6 == line 450 + //Ireturn 7 == line 440 + //Ireturn 8 == line 682 + //Ireturn 9 == line 704 + //Ireturn 10 == line 705 + //Ireturn 11 == line 706 + //Ireturn 12 == line 707 + //Ireturn 13 == line 708 + //Ireturn 14 == line 709 + //Ireturn 15 == line 710 + //Ireturn -1 == line 010 + // Check status + { + int encpasswdok = 0; - account->ban_until_time = atol(sql_row[8]); - state = atoi(sql_row[9]); + if (atoi(sql_row[9]) == -3) { + //id is banned + mysql_free_result(sql_res); + return -3; + } else if (atoi(sql_row[9]) == -2) { //dynamic ban + //id is banned + mysql_free_result(sql_res); + //add IP list. + return -2; + } - if (state) { - switch(state) { // packet 0x006a value + 1 + if (use_md5_passwds) { + MD5_String(account->passwd,user_password); + } else { + jstrescapecpy(user_password, account->passwd); + } + printf("account id ok encval:%d\n",account->passwdenc); +#ifdef PASSWORDENC + if (account->passwdenc > 0) { + int j = account->passwdenc; + printf ("start md5calc..\n"); + if (j > 2) + j = 1; + do { + if (j == 1) { + sprintf(md5str, "%s%s", md5key,sql_row[2]); + } else if (j == 2) { + sprintf(md5str, "%s%s", sql_row[2], md5key); + } else + md5str[0] = 0; + printf("j:%d mdstr:%s\n", j, md5str); + MD5_String2binary(md5str, md5bin); + encpasswdok = (memcmp(user_password, md5bin, 16) == 0); + } while (j < 2 && !encpasswdok && (j++) != account->passwdenc); + //printf("key[%s] md5 [%s] ", md5key, md5); + printf("client [%s] accountpass [%s]\n", user_password, sql_row[2]); + printf ("end md5calc..\n"); + } +#endif + if ((strcmp(user_password, sql_row[2]) && !encpasswdok)) { + if (account->passwdenc == 0) { + printf ("auth failed pass error %s %s %s" RETCODE, tmpstr, account->userid, user_password); +#ifdef PASSWORDENC + } else { + char logbuf[1024], *p = logbuf; + int j; + p += sprintf(p, "auth failed pass error %s %s recv-md5[", tmpstr, account->userid); + for(j = 0; j < 16; j++) + p += sprintf(p, "%02x", ((unsigned char *)user_password)[j]); + p += sprintf(p, "] calc-md5["); + for(j = 0; j < 16; j++) + p += sprintf(p, "%02x", ((unsigned char *)md5bin)[j]); + p += sprintf(p, "] md5key["); + for(j = 0; j < md5keylen; j++) + p += sprintf(p, "%02x", ((unsigned char *)md5key)[j]); + p += sprintf(p, "]" RETCODE); + printf("%s\n", p); +#endif + } + return 1; + } + printf("auth ok %s %s" RETCODE, tmpstr, account->userid); + } + +/* +// do not remove this section. this is meant for future, and current forums usage +// as a login manager and CP for login server. [CLOWNISIUS] + if (atoi(sql_row[10]) == 1) { + return 4; + } + + if (atoi(sql_row[10]) >= 5) { + switch(atoi(sql_row[10])) { + case 5: + return 5; + break; + case 6: + return 7; + break; + case 7: + return 9; + break; + case 8: + return 10; + break; + case 9: + return 11; + break; + default: + return 10; + break; + } + } +*/ + ban_until_time = atol(sql_row[8]); + + //login {0-account_id/1-userid/2-user_pass/3-lastlogin/4-logincount/5-sex/6-connect_untl/7-last_ip/8-ban_until/9-state} + if (ban_until_time != 0) { // if account is banned + strftime(tmpstr, 20, date_format, localtime(&ban_until_time)); + tmpstr[19] = '\0'; + if (ban_until_time > time(NULL)) { // always banned + return 6; // 6 = Your are Prohibited to log in until %s + } else { // ban is finished + // reset the ban time + if (atoi(sql_row[9])==7) {//it was a temp ban - so we set STATE to 0 + sprintf(tmpsql, "UPDATE `%s` SET `ban_until`='0', `state`='0' WHERE %s `%s`='%s'", login_db, case_sensitive ? "BINARY" : "", login_db_userid, t_uid); + strcpy(sql_row[9],"0"); //we clear STATE + } else //it was a permanent ban + temp ban. So we leave STATE = 5, but clear the temp ban + sprintf(tmpsql, "UPDATE `%s` SET `ban_until`='0' WHERE %s `%s`='%s'", login_db, case_sensitive ? "BINARY" : "", login_db_userid, t_uid); + + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + } + } + + if (atoi(sql_row[9])) { + switch(atoi(sql_row[9])) { // packet 0x006a value + 1 case 1: // 0 = Unregistered ID case 2: // 1 = Incorrect Password case 3: // 2 = This ID is expired case 4: // 3 = Rejected from Server case 5: // 4 = You have been blocked by the GM Team case 6: // 5 = Your Game's EXE file is not the latest version + case 7: // 6 = Your are Prohibited to log in until %s case 8: // 7 = Server is jammed due to over populated case 9: // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this) case 100: // 99 = This ID has been totally erased - #ifdef DEBUG - printf("Auth Error #%d\n", state); - #endif - mysql_free_result(sql_res); - return state; + printf("Auth Error #%d\n", atoi(sql_row[9])); + return atoi(sql_row[9]) - 1; break; - case 7: // 6 = Your are Prohibited to log in until %s - strftime(tmpstr, 20, date_format, localtime(&account->ban_until_time)); - tmpstr[19] = '\0'; - if (account->ban_until_time > time(NULL)) { // always banned - mysql_free_result(sql_res); - return 7; - } else { // ban is finished - // reset the ban time - sprintf(tmpsql, "UPDATE `%s` SET `ban_until`='0',`state`='0' WHERE BINARY `%s`='%s'", login_db, login_db_userid, t_uid); - sql_query(tmpsql,"mmo_auth"); - } - break; default: - return 100; // 99 = ID has been totally erased + return 99; // 99 = ID has been totally erased break; } } @@ -439,117 +600,492 @@ int mmo_auth( struct mmo_account* account , int fd){ return 2; // 2 = This ID is expired } - if ( is_user_online(atol(sql_row[0])) ) { - printf("User [%s] is already online - Rejected.\n",sql_row[1]); - return 3; // Rejected - } + if ( is_user_online(atol(sql_row[0])) && register_users_online > 0) { + printf("User [%s] is already online - Rejected.\n",sql_row[1]); +#ifndef TWILIGHT + return 3; // Rejected +#endif + } - if (use_md5_passwds) { - MD5_String(account->passwd,user_password); - } else { - jstrescapecpy(user_password, account->passwd); + account->account_id = atoi(sql_row[0]); + account->login_id1 = rand(); + account->login_id2 = rand(); + memcpy(tmpstr, sql_row[3], 19); + memcpy(account->lastlogin, tmpstr, 24); + account->sex = sql_row[5][0] == 'S' ? 2 : sql_row[5][0]=='M'; + + sprintf(tmpsql, "UPDATE `%s` SET `lastlogin` = NOW(), `logincount`=`logincount` +1, `last_ip`='%s' WHERE %s `%s` = '%s'", + login_db, ip, case_sensitive ? "BINARY" : "", login_db_userid, sql_row[1]); + mysql_free_result(sql_res) ; //resource free + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); } - #ifdef DEBUG - printf("Account [ok] Pass Encode Value: [%d]\n",account->passwdenc); - #endif + return -1; +} -#ifdef PASSWORDENC - if (account->passwdenc > 0) { - j = account->passwdenc; +// Send to char +int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) { + int i, c; + int fd; + + c = 0; + for(i = 0; i < MAX_SERVERS; i++) { + if ((fd = server_fd[i]) > 0 && fd != sfd) { + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + c++; + } + } + return c; +} - #ifdef DEBUG - printf ("Starting md5calc..\n"); - #endif +//----------------------------------------------------- +// char-server packet parse +//----------------------------------------------------- +int parse_fromchar(int fd){ + int i, id; + MYSQL_RES* sql_res; + MYSQL_ROW sql_row = NULL; - if (j > 2) - j = 1; + unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr; + char ip[16]; - do { - if (j == 1) { - sprintf(md5str, "%s%s", md5key,sql_row[2]); - } else if (j == 2) { - sprintf(md5str, "%s%s", sql_row[2], md5key); - } else - md5str[0] = 0; - #ifdef DEBUG - printf("j: [%d] mdstr: [%s]\n", j, md5str); - #endif + sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - MD5_String2binary(md5str, md5bin); - encpasswdok = (memcmp(user_password, md5bin, 16) == 0); - } while (j < 2 && !encpasswdok && (j++) != account->passwdenc); + for(id = 0; id < MAX_SERVERS; id++) + if (server_fd[id] == fd) + break; - #ifdef DEBUG - printf("key [%s] md5 [%s] ", md5key, md5str); - printf("client [%s] accountpass [%s]\n", user_password, sql_row[2]); - printf ("end md5calc..\n"); - #endif + if (id == MAX_SERVERS) + session[fd]->eof = 1; + if(session[fd]->eof) { + if (id < MAX_SERVERS) { + printf("Char-server '%s' has disconnected.\n", server[id].name); + server_fd[id] = -1; + memset(&server[id], 0, sizeof(struct mmo_char_server)); + // server delete + sprintf(tmpsql, "DELETE FROM `sstatus` WHERE `index`='%d'", id); + // query + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + } + close(fd); + delete_session(fd); + return 0; } + + while(RFIFOREST(fd) >= 2) { +// printf("char_parse: %d %d packet case=%x\n", fd, RFIFOREST(fd), RFIFOW(fd, 0)); + + switch (RFIFOW(fd,0)) { + case 0x2712: + if (RFIFOREST(fd) < 19) + return 0; + { + int account_id; + account_id = RFIFOL(fd,2); // speed up + for(i=0;i<AUTH_FIFO_SIZE;i++){ + if (auth_fifo[i].account_id == account_id && + auth_fifo[i].login_id1 == RFIFOL(fd,6) && +#if CMP_AUTHFIFO_LOGIN2 != 0 + auth_fifo[i].login_id2 == RFIFOL(fd,10) && // relate to the versions higher than 18 #endif - if ((strcmp(user_password, sql_row[2]) && !encpasswdok)) { - if (account->passwdenc == 0) { - #ifdef DEBUG - printf ("auth failed pass error %s %s %s" RETCODE, tmpstr, account->userid, user_password); - #endif -#ifdef PASSWORDENC - } else { - p += sprintf(p, "auth failed pass error %s %s recv-md5[", tmpstr, account->userid); + auth_fifo[i].sex == RFIFOB(fd,14) && +#if CMP_AUTHFIFO_IP != 0 + auth_fifo[i].ip == RFIFOL(fd,15) && +#endif + !auth_fifo[i].delflag) { + auth_fifo[i].delflag = 1; + printf("auth -> %d\n", i); + break; + } + } - for(j = 0; j < 16; j++) - p += sprintf(p, "%02x", ((unsigned char *)user_password)[j]); + if (i != AUTH_FIFO_SIZE) { // send account_reg + int p; + time_t connect_until_time = 0; + char email[40] = ""; + account_id=RFIFOL(fd,2); + sprintf(tmpsql, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id); + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle) ; + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); + connect_until_time = atol(sql_row[1]); + strcpy(email, sql_row[0]); + } + mysql_free_result(sql_res); + if (account_id > 0) { + sprintf(tmpsql, "SELECT `str`,`value` FROM `global_reg_value` WHERE `type`='1' AND `account_id`='%d'",account_id); + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle) ; + if (sql_res) { + WFIFOW(fd,0) = 0x2729; + WFIFOL(fd,4) = account_id; + for(p = 8; (sql_row = mysql_fetch_row(sql_res));p+=36){ + memcpy(WFIFOP(fd,p), sql_row[0], 32); + WFIFOL(fd,p+32) = atoi(sql_row[1]); + } + WFIFOW(fd,2) = p; + WFIFOSET(fd,p); + //printf("account_reg2 send : login->char (auth fifo)\n"); + WFIFOW(fd,0) = 0x2713; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = 0; + memcpy(WFIFOP(fd, 7), email, 40); + WFIFOL(fd,47) = (unsigned long) connect_until_time; + WFIFOSET(fd,51); + } + mysql_free_result(sql_res); + } + } else { + WFIFOW(fd,0) = 0x2713; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = 1; + WFIFOSET(fd,51); + } + } + RFIFOSKIP(fd,19); + break; - p += sprintf(p, "] calc-md5["); + case 0x2714: + if (RFIFOREST(fd) < 6) + return 0; + // how many users on world? (update) + if (server[id].users != RFIFOL(fd,2)) + { + printf("set users %s : %d\n", server[id].name, RFIFOL(fd,2)); + + server[id].users = RFIFOL(fd,2); + sprintf(tmpsql,"UPDATE `sstatus` SET `user` = '%d' WHERE `index` = '%d'", server[id].users, id); + // query + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + } - for(j = 0; j < 16; j++) - p += sprintf(p, "%02x", ((unsigned char *)md5bin)[j]); + // send some answer + WFIFOW(fd,0) = 0x2718; + WFIFOSET(fd,2); - p += sprintf(p, "] md5key["); + RFIFOSKIP(fd,6); + break; - for(j = 0; j < md5keylen; j++) - p += sprintf(p, "%02x", ((unsigned char *)md5key)[j]); + // We receive an e-mail/limited time request, because a player comes back from a map-server to the char-server + case 0x2716: + if (RFIFOREST(fd) < 6) + return 0; + { + int account_id; + time_t connect_until_time = 0; + char email[40] = ""; + account_id=RFIFOL(fd,2); + sprintf(tmpsql,"SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'",login_db, login_db_account_id, account_id); + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle) ; + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); + connect_until_time = atol(sql_row[1]); + strcpy(email, sql_row[0]); + } + mysql_free_result(sql_res); + //printf("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, RFIFOL(fd,2)); + WFIFOW(fd,0) = 0x2717; + WFIFOL(fd,2) = RFIFOL(fd,2); + memcpy(WFIFOP(fd, 6), email, 40); + WFIFOL(fd,46) = (unsigned long) connect_until_time; + WFIFOSET(fd,50); + } + RFIFOSKIP(fd,6); + break; - p += sprintf(p, "]" RETCODE); + case 0x2720: // GM + if (RFIFOREST(fd) < 4) + return 0; + if (RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + //oldacc = RFIFOL(fd,4); + printf("change GM isn't support in this login server version.\n"); + printf("change GM error 0 %s\n", RFIFOP(fd, 8)); + + RFIFOSKIP(fd, RFIFOW(fd, 2)); + WFIFOW(fd, 0) = 0x2721; + WFIFOL(fd, 2) = RFIFOL(fd,4); // oldacc; + WFIFOL(fd, 6) = 0; // newacc; + WFIFOSET(fd, 10); + return 0; - #ifdef DEBUG - printf("%s\n", p); - #endif -#endif - } - return 2; - } + // Map server send information to change an email of an account via char-server + case 0x2722: // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B + if (RFIFOREST(fd) < 86) + return 0; + { + int acc; + char actual_email[40], new_email[40]; + acc = RFIFOL(fd,2); + memcpy(actual_email, RFIFOP(fd,6), 40); + memcpy(new_email, RFIFOP(fd,46), 40); + if (e_mail_check(actual_email) == 0) + printf("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)" RETCODE, + server[id].name, acc, ip); + else if (e_mail_check(new_email) == 0) + printf("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)" RETCODE, + server[id].name, acc, ip); + else if (strcmpi(new_email, "a@a.com") == 0) + printf("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)" RETCODE, + server[id].name, acc, ip); + else { + sprintf(tmpsql, "SELECT `%s`,`email` FROM `%s` WHERE `%s` = '%d'", login_db_userid, login_db, login_db_account_id, acc); + if (mysql_query(&mysql_handle, tmpsql)) + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); //row fetching + + if (strcmpi(sql_row[1], actual_email) == 0) { + sprintf(tmpsql, "UPDATE `%s` SET `email` = '%s' WHERE `%s` = '%d'", login_db, new_email, login_db_account_id, acc); + // query + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + printf("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s)." RETCODE, + server[id].name, acc, sql_row[0], actual_email, ip); + } + } - #ifdef DEBUG - printf("Auth ok: Time: [%s] Username: [%s]\n" RETCODE, tmpstr, account->userid); - #endif + } + } + RFIFOSKIP(fd, 86); + break; - account->account_id = atoi(sql_row[0]); - account->login_id1 = rand(); - account->login_id2 = rand(); - memcpy(tmpstr, sql_row[3], 19); - memcpy(account->lastlogin, tmpstr, 24); - account->sex = sql_row[5][0] == 'S' ? 2 : sql_row[5][0]=='M'; + case 0x2724: // Receiving of map-server via char-server a status change resquest (by Yor) + if (RFIFOREST(fd) < 10) + return 0; + { + int acc, statut; + acc = RFIFOL(fd,2); + statut = RFIFOL(fd,6); + sprintf(tmpsql, "SELECT `state` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, acc); + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); // row fetching + } + if (atoi(sql_row[0]) != statut && statut != 0) { + unsigned char buf[16]; + WBUFW(buf,0) = 0x2731; + WBUFL(buf,2) = acc; + WBUFB(buf,6) = 0; // 0: change of statut, 1: ban + WBUFL(buf,7) = statut; // status or final date of a banishment + charif_sendallwos(-1, buf, 11); + } + sprintf(tmpsql,"UPDATE `%s` SET `state` = '%d' WHERE `%s` = '%d'", login_db, statut,login_db_account_id,acc); + //query + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + RFIFOSKIP(fd,10); + } + return 0; - sprintf(tmpsql, "UPDATE `%s` SET `lastlogin` = NOW(), `logincount`=`logincount` +1, `last_ip`='%s' WHERE BINARY `%s` = '%s'", - login_db, ip, login_db_userid, sql_row[1]); - sql_query(tmpsql,"mmo_auth"); + case 0x2725: // Receiving of map-server via char-server a ban resquest (by Yor) + if (RFIFOREST(fd) < 18) + return 0; + { + int acc; + struct tm *tmtime; + time_t timestamp, tmptime; + acc = RFIFOL(fd,2); + sprintf(tmpsql, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc); + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle); + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); // row fetching + } + tmptime = atol(sql_row[0]); + if (tmptime == 0 || tmptime < time(NULL)) + timestamp = time(NULL); + else + timestamp = tmptime; + tmtime = localtime(×tamp); + tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,6); + tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,8); + tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,10); + tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,12); + tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,14); + tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,16); + timestamp = mktime(tmtime); + if (timestamp != -1) { + if (timestamp <= time(NULL)) + timestamp = 0; + if (tmptime != timestamp) { + if (timestamp != 0) { + unsigned char buf[16]; + WBUFW(buf,0) = 0x2731; + WBUFL(buf,2) = acc; + WBUFB(buf,6) = 1; // 0: change of statut, 1: ban + WBUFL(buf,7) = timestamp; // status or final date of a banishment + charif_sendallwos(-1, buf, 11); + } + printf("Account: %d Banned until: %ld\n", acc, timestamp); + sprintf(tmpsql, "UPDATE `%s` SET `ban_until` = '%ld', `state`='7' WHERE `%s` = '%d'", login_db, timestamp, login_db_account_id, acc); + // query + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + } + } + RFIFOSKIP(fd,18); + break; + } + return 0; - mysql_free_result(sql_res) ; //resource free + case 0x2727: + if (RFIFOREST(fd) < 6) + return 0; + { + int acc,sex; + unsigned char buf[16]; + acc=RFIFOL(fd,4); + sprintf(tmpsql,"SELECT `sex` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc); + + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + return 0; + } + + sql_res = mysql_store_result(&mysql_handle) ; + + if (sql_res) { + if (mysql_num_rows(sql_res) == 0) { + mysql_free_result(sql_res); + return 0; + } + sql_row = mysql_fetch_row(sql_res); //row fetching + } + + if (strcmpi(sql_row[0], "M") == 0) + sex = 1; + else + sex = 0; + sprintf(tmpsql,"UPDATE `%s` SET `sex` = '%c' WHERE `%s` = '%d'", login_db, (sex==0?'M':'F'), login_db_account_id, acc); + //query + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + WBUFW(buf,0) = 0x2723; + WBUFL(buf,2) = acc; + WBUFB(buf,6) = sex; + charif_sendallwos(-1, buf, 7); + RFIFOSKIP(fd,6); + } + return 0; + + case 0x2728: // save account_reg + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + { + int acc,p,j; + char str[32]; + char temp_str[32]; + int value; + acc=RFIFOL(fd,4); + + if (acc>0){ + unsigned char buf[RFIFOW(fd,2)+1]; + for(p=8,j=0;p<RFIFOW(fd,2) && j<ACCOUNT_REG2_NUM;p+=36,j++){ + memcpy(str,RFIFOP(fd,p),32); + value=RFIFOL(fd,p+32); + sprintf(tmpsql,"DELETE FROM `global_reg_value` WHERE `type`='1' AND `account_id`='%d' AND `str`='%s';",acc,jstrescapecpy(temp_str,str)); + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sprintf(tmpsql,"INSERT INTO `global_reg_value` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , '%s' , '%d');", acc, jstrescapecpy(temp_str,str), value); + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + } + + // Send to char + memcpy(WBUFP(buf,0),RFIFOP(fd,0),RFIFOW(fd,2)); + WBUFW(buf,0)=0x2729; + charif_sendallwos(fd,buf,WBUFW(buf,2)); + } + } + RFIFOSKIP(fd,RFIFOW(fd,2)); + //printf("login: save account_reg (from char)\n"); + break; + + case 0x272a: // Receiving of map-server via char-server a unban resquest (by Yor) + if (RFIFOREST(fd) < 6) + return 0; + { + int acc; + acc = RFIFOL(fd,2); + sprintf(tmpsql,"SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc); + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle) ; + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); //row fetching + } + if (atol(sql_row[0]) != 0) { + sprintf(tmpsql,"UPDATE `%s` SET `ban_until` = '0', `state`='0' WHERE `%s` = '%d'", login_db,login_db_account_id,acc); + //query + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + break; + } + RFIFOSKIP(fd,6); + } + return 0; - return -1; + case 0x272b: // Set account_id to online [Wizputer] + if (RFIFOREST(fd) < 6) + return 0; + add_online_user(RFIFOL(fd,2)); + RFIFOSKIP(fd,6); + break; + + case 0x272c: // Set account_id to offline [Wizputer] + if (RFIFOREST(fd) < 6) + return 0; + remove_online_user(RFIFOL(fd,2)); + RFIFOSKIP(fd,6); + break; + + default: + printf("login: unknown packet %x! (from char).\n", RFIFOW(fd,0)); + session[fd]->eof = 1; + return 0; + } + } + + return 0; } -//----------------------------------------- -// Lan ip check ( added by Kashy ) -//----------------------------------------- +//Lan ip check added by Kashy int lan_ip_check(unsigned char *p) { int y; int lancheck = 1; int lancharip[4]; unsigned int k0, k1, k2, k3; - sscanf(lan_char_ip, "%d.%d.%d.%d", &k0, &k1, &k2, &k3); lancharip[0] = k0; lancharip[1] = k1; lancharip[2] = k2; lancharip[3] = k3; @@ -558,35 +1094,392 @@ int lan_ip_check(unsigned char *p) { lancheck = 0; break; } - #ifdef DEBUG printf("LAN check: %s.\n", (lancheck) ? "\033[1;32mLAN\033[0m" : "\033[1;31mWAN\033[0m"); - #endif - return lancheck; } +//---------------------------------------------------------------------------------------- +// Default packet parsing (normal players or administation/char-server connection requests) +//---------------------------------------------------------------------------------------- +int parse_login(int fd) { + //int len; -//----------------------------------------------------- -// BANNED IP CHECK. -//----------------------------------------------------- -int ip_ban_check(int tid, unsigned int tick, int id, int data){ + MYSQL_RES* sql_res ; + MYSQL_ROW sql_row = NULL; - //query - if(mysql_query(&mysql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()")) { - printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + char t_uid[100]; + //int sql_fields, sql_cnt; + struct mmo_account account; + + int result, i; + unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr; + char ip[16]; + + sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + + memset(&account, 0, sizeof(account)); + + if (ipban > 0) { + //ip ban + //p[0], p[1], p[2], p[3] + //request DB connection + //check + sprintf(tmpsql, "SELECT count(*) FROM `ipbanlist` WHERE `list` = '%d.*.*.*' OR `list` = '%d.%d.*.*' OR `list` = '%d.%d.%d.*' OR `list` = '%d.%d.%d.%d'", + p[0], p[0], p[1], p[0], p[1], p[2], p[0], p[1], p[2], p[3]); + if (mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + + sql_res = mysql_store_result(&mysql_handle) ; + sql_row = mysql_fetch_row(sql_res); //row fetching + + if (atoi(sql_row[0]) >0) { + // ip ban ok. + printf ("packet from banned ip : %d.%d.%d.%d" RETCODE, p[0], p[1], p[2], p[3]); + sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', 'unknown','-3', 'ip banned')", loginlog_db, p[0], p[1], p[2], p[3]); + + // query + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + printf ("close session connection...\n"); + + // close connection + session[fd]->eof = 1; + + } else { + printf ("packet from ip (ban check ok) : %d.%d.%d.%d" RETCODE, p[0], p[1], p[2], p[3]); + } + mysql_free_result(sql_res); + } + + if (session[fd]->eof) { + for(i = 0; i < MAX_SERVERS; i++) + if (server_fd[i] == fd) + server_fd[i] = -1; + close(fd); + delete_session(fd); + return 0; + } + + while(RFIFOREST(fd)>=2){ + printf("parse_login : %d %d packet case=%x\n", fd, RFIFOREST(fd), RFIFOW(fd,0)); + + switch(RFIFOW(fd,0)){ + case 0x200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive. + if (RFIFOREST(fd) < 26) + return 0; + RFIFOSKIP(fd,26); + break; + + case 0x204: // New alive packet: structure: 0x204 <encrypted.account.userid>.16B. (new ragexe from 22 june 2004) + if (RFIFOREST(fd) < 18) + return 0; + RFIFOSKIP(fd,18); + break; + + case 0x64: // request client login + case 0x01dd: // request client login with encrypt + if(RFIFOREST(fd)< ((RFIFOW(fd, 0) ==0x64)?55:47)) + return 0; + + printf("client connection request %s from %d.%d.%d.%d\n", RFIFOP(fd, 6), p[0], p[1], p[2], p[3]); + account.version = RFIFOL(fd, 2); + account.userid = (char*)RFIFOP(fd, 6); + account.passwd = (char*)RFIFOP(fd, 30); +#ifdef PASSWORDENC + account.passwdenc= (RFIFOW(fd,0)==0x64)?0:PASSWORDENC; +#else + account.passwdenc=0; +#endif + result=mmo_auth(&account, fd); + + + jstrescapecpy(t_uid,(char*)RFIFOP(fd, 6)); + if(result==-1){ + int gm_level = isGM(account.account_id); + + if (min_level_to_connect > gm_level) { + WFIFOW(fd,0) = 0x81; + WFIFOL(fd,2) = 1; // 01 = Server closed + WFIFOSET(fd,3); + } else { + + if (p[0] != 127) { + sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s','100', 'login ok')", loginlog_db, p[0], p[1], p[2], p[3], t_uid); + //query + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + } + if (gm_level) + printf("Connection of the GM (level:%d) account '%s' accepted.\n", gm_level, account.userid); + else + printf("Connection of the account '%s' accepted.\n", account.userid); + server_num=0; + for(i = 0; i < MAX_SERVERS; i++) { + if (server_fd[i] >= 0) { + //Lan check added by Kashy + if (lan_ip_check(p)) + WFIFOL(fd,47+server_num*32) = inet_addr(lan_char_ip); + else + WFIFOL(fd,47+server_num*32) = server[i].ip; + WFIFOW(fd,47+server_num*32+4) = server[i].port; + memcpy(WFIFOP(fd,47+server_num*32+6), server[i].name, 20); + WFIFOW(fd,47+server_num*32+26) = server[i].users; + WFIFOW(fd,47+server_num*32+28) = server[i].maintenance; + WFIFOW(fd,47+server_num*32+30) = server[i].new_; + server_num++; + } + } + // if at least 1 char-server + if (server_num > 0) { + WFIFOW(fd,0)=0x69; + WFIFOW(fd,2)=47+32*server_num; + WFIFOL(fd,4)=account.login_id1; + WFIFOL(fd,8)=account.account_id; + WFIFOL(fd,12)=account.login_id2; + WFIFOL(fd,16)=0; + memcpy(WFIFOP(fd,20),account.lastlogin,24); + WFIFOB(fd,46)=account.sex; + WFIFOSET(fd,47+32*server_num); + if(auth_fifo_pos>=AUTH_FIFO_SIZE) + auth_fifo_pos=0; + auth_fifo[auth_fifo_pos].account_id=account.account_id; + auth_fifo[auth_fifo_pos].login_id1=account.login_id1; + auth_fifo[auth_fifo_pos].login_id2=account.login_id2; + auth_fifo[auth_fifo_pos].sex=account.sex; + auth_fifo[auth_fifo_pos].delflag=0; + auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr; + auth_fifo_pos++; + } else { + WFIFOW(fd,0) = 0x81; + WFIFOL(fd,2) = 1; // 01 = Server closed + WFIFOSET(fd,3); + } + } + } else { + char tmp_sql[512]; + char error[64]; + sprintf(tmp_sql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s', '%d','login failed : %%s')", loginlog_db, p[0], p[1], p[2], p[3], t_uid, result); + switch((result + 1)) { + case -2: //-3 = Account Banned + sprintf(tmpsql,tmp_sql,"Account banned."); + sprintf(error,"Account banned."); + break; + case -1: //-2 = Dynamic Ban + sprintf(tmpsql,tmp_sql,"dynamic ban (ip and account)."); + sprintf(error,"dynamic ban (ip and account)."); + break; + case 1: // 0 = Unregistered ID + sprintf(tmpsql,tmp_sql,"Unregisterd ID."); + sprintf(error,"Unregisterd ID."); + break; + case 2: // 1 = Incorrect Password + sprintf(tmpsql,tmp_sql,"Incorrect Password."); + sprintf(error,"Incorrect Password."); + break; + case 3: // 2 = This ID is expired + sprintf(tmpsql,tmp_sql,"Account Expired."); + sprintf(error,"Account Expired."); + break; + case 4: // 3 = Rejected from Server + sprintf(tmpsql,tmp_sql,"Rejected from server."); + sprintf(error,"Rejected from server."); + break; + case 5: // 4 = You have been blocked by the GM Team + sprintf(tmpsql,tmp_sql,"Blocked by GM."); + sprintf(error,"Blocked by GM."); + break; + case 6: // 5 = Your Game's EXE file is not the latest version + sprintf(tmpsql,tmp_sql,"Not latest game EXE."); + sprintf(error,"Not latest game EXE."); + break; + case 7: // 6 = Your are Prohibited to log in until %s + sprintf(tmpsql,tmp_sql,"Banned."); + sprintf(error,"Banned."); + break; + case 8: // 7 = Server is jammed due to over populated + sprintf(tmpsql,tmp_sql,"Server Over-population."); + sprintf(error,"Server Over-population."); + break; + case 9: // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this) + sprintf(tmpsql,tmp_sql," "); + sprintf(error," "); + break; + case 100: // 99 = This ID has been totally erased + sprintf(tmpsql,tmp_sql,"Account gone."); + sprintf(error,"Account gone."); + break; + default: + sprintf(tmpsql,tmp_sql,"Uknown Error."); + sprintf(error,"Uknown Error."); + break; + } + //query + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + if ((result == 1) && (dynamic_pass_failure_ban != 0)){ // failed password + sprintf(tmpsql,"SELECT count(*) FROM `%s` WHERE `ip` = '%d.%d.%d.%d' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE", + loginlog_db, p[0], p[1], p[2], p[3], dynamic_pass_failure_ban_time); //how many times filed account? in one ip. + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + //check query result + sql_res = mysql_store_result(&mysql_handle) ; + sql_row = mysql_fetch_row(sql_res); //row fetching + + if (atoi(sql_row[0]) >= dynamic_pass_failure_ban_how_many ) { + sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban: %s')", p[0], p[1], p[2], dynamic_pass_failure_ban_how_long, t_uid); + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + } + mysql_free_result(sql_res); + } + else if (result == -2){ //dynamic banned - add ip to ban list. + sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL 1 MONTH ,'Dynamic banned user id : %s')", p[0], p[1], p[2], t_uid); + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + result = -3; + }else if(result == 6){ //not lastet version .. + //result = 5; + } + + sprintf(tmpsql,"SELECT `ban_until` FROM `%s` WHERE %s `%s` = '%s'",login_db, case_sensitive ? "BINARY" : "",login_db_userid, t_uid); + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + sql_res = mysql_store_result(&mysql_handle) ; + if (sql_res) { + sql_row = mysql_fetch_row(sql_res); //row fetching + } + //cannot connect login failed + memset(WFIFOP(fd,0),'\0',23); + WFIFOW(fd,0)=0x6a; + WFIFOB(fd,2)=result; + if (result == 6) { // 6 = Your are Prohibited to log in until %s + if (atol(sql_row[0]) != 0) { // if account is banned, we send ban timestamp + char tmpstr[256]; + time_t ban_until_time; + ban_until_time = atol(sql_row[0]); + strftime(tmpstr, 20, date_format, localtime(&ban_until_time)); + tmpstr[19] = '\0'; + memcpy(WFIFOP(fd,3), tmpstr, 20); + } else { // we send error message + memcpy(WFIFOP(fd,3), error, 20); + } + } + WFIFOSET(fd,23); + } + RFIFOSKIP(fd,(RFIFOW(fd,0)==0x64)?55:47); + break; + + case 0x01db: // request password key + if (session[fd]->session_data) { + printf("login: abnormal request of MD5 key (already opened session).\n"); + session[fd]->eof = 1; + return 0; + } + printf("Request Password key -%s\n",md5key); + RFIFOSKIP(fd,2); + WFIFOW(fd,0)=0x01dc; + WFIFOW(fd,2)=4+md5keylen; + memcpy(WFIFOP(fd,4),md5key,md5keylen); + WFIFOSET(fd,WFIFOW(fd,2)); + break; + + case 0x2710: // request Char-server connection + if(RFIFOREST(fd)<86) + return 0; + { + unsigned char* server_name; + sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s@%s','100', 'charserver - %s@%d.%d.%d.%d:%d')", loginlog_db, p[0], p[1], p[2], p[3], RFIFOP(fd, 2),RFIFOP(fd, 60),RFIFOP(fd, 60), RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58)); + + //query + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + printf("server connection request %s @ %d.%d.%d.%d:%d (%d.%d.%d.%d)\n", + RFIFOP(fd, 60), RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58), + p[0], p[1], p[2], p[3]); + account.userid = (char*)RFIFOP(fd, 2); + account.passwd = (char*)RFIFOP(fd, 26); + account.passwdenc = 0; + server_name = RFIFOP(fd,60); + result = mmo_auth(&account, fd); + //printf("Result: %d - Sex: %d - Account ID: %d\n",result,account.sex,(int) account.account_id); + + if(result == -1 && account.sex==2 && account.account_id<MAX_SERVERS && server_fd[account.account_id]==-1){ + printf("Connection of the char-server '%s' accepted.\n", server_name); + memset(&server[account.account_id], 0, sizeof(struct mmo_char_server)); + server[account.account_id].ip=RFIFOL(fd,54); + server[account.account_id].port=RFIFOW(fd,58); + memcpy(server[account.account_id].name,RFIFOP(fd,60),20); + server[account.account_id].users=0; + server[account.account_id].maintenance=RFIFOW(fd,82); + server[account.account_id].new_=RFIFOW(fd,84); + server_fd[account.account_id]=fd; + sprintf(tmpsql,"DELETE FROM `sstatus` WHERE `index`='%ld'", account.account_id); + //query + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + + jstrescapecpy(t_uid,server[account.account_id].name); + sprintf(tmpsql,"INSERT INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%ld', '%s', '%d')", + account.account_id, server[account.account_id].name,0); + //query + if(mysql_query(&mysql_handle, tmpsql)) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + WFIFOW(fd,0)=0x2711; + WFIFOB(fd,2)=0; + WFIFOSET(fd,3); + session[fd]->func_parse=parse_fromchar; + realloc_fifo(fd,FIFOSIZE_SERVERLINK,FIFOSIZE_SERVERLINK); + } else { + WFIFOW(fd, 0) =0x2711; + WFIFOB(fd, 2)=3; + WFIFOSET(fd, 3); + } + } + RFIFOSKIP(fd, 86); + return 0; + + case 0x7530: // request Athena information + WFIFOW(fd,0)=0x7531; + WFIFOB(fd,2)=ATHENA_MAJOR_VERSION; + WFIFOB(fd,3)=ATHENA_MINOR_VERSION; + WFIFOB(fd,4)=ATHENA_REVISION; + WFIFOB(fd,5)=ATHENA_RELEASE_FLAG; + WFIFOB(fd,6)=ATHENA_OFFICIAL_FLAG; + WFIFOB(fd,7)=ATHENA_SERVER_LOGIN; + WFIFOW(fd,8)=ATHENA_MOD_VERSION; + WFIFOSET(fd,10); + RFIFOSKIP(fd,2); + printf ("Athena version check...\n"); + break; + + case 0x7532: + default: + printf ("End of connection (ip: %s)" RETCODE, ip); + session[fd]->eof = 1; + return 0; + } } return 0; } -//------------------------------------ // Console Command Parser [Wizputer] -//------------------------------------ int parse_console(char *buf) { char *type,*command; - type = (char *)malloc(64); - command = (char *)malloc(64); + type = (char *)aMalloc(64); + command = (char *)aMalloc(64); memset(type,0,64); memset(command,0,64); @@ -598,9 +1491,9 @@ int parse_console(char *buf) { printf("Type of command: %s || Command: %s \n",type,command); - if(buf) free(buf); - if(type) free(type); - if(command) free(command); + if(buf) aFree(buf); + if(type) aFree(type); + if(command) aFree(command); return 0; } @@ -619,9 +1512,7 @@ int config_switch(const char *str) { } -//------------------------------- -// LAN Support Config (Kashy) -//------------------------------- +//Lan Support conf reading added by Kashy int login_lan_config_read(const char *lancfgName){ int i; char subnetmask[128]; @@ -676,12 +1567,28 @@ int login_lan_config_read(const char *lancfgName){ } //----------------------------------------------------- -// Login configuration +//BANNED IP CHECK. +//----------------------------------------------------- +int ip_ban_check(int tid, unsigned int tick, int id, int data){ + + //query + if(mysql_query(&mysql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()")) { + printf("DB server Error - %s\n", mysql_error(&mysql_handle)); + } + + return 0; +} + +//----------------------------------------------------- +// reading configuration //----------------------------------------------------- int login_config_read(const char *cfgName){ int i; char line[1024], w1[1024], w2[1024]; FILE *fp; + struct hostent *h = NULL; + + bind_ip_str[0] = '\0'; fp=fopen(cfgName,"r"); @@ -689,7 +1596,7 @@ int login_config_read(const char *cfgName){ printf("Configuration file (%s) not found.\n", cfgName); return 1; } - printf("Start reading login configuration: %s\n", cfgName); + printf ("start reading configuration...\n"); while(fgets(line, sizeof(line)-1, fp)){ if(line[0] == '/' && line[1] == '/') continue; @@ -697,8 +1604,15 @@ int login_config_read(const char *cfgName){ i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2); if(i!=2) continue; - - else if(strcmpi(w1,"login_port")==0){ + else if (strcmpi(w1, "bind_ip") == 0) { + //bind_ip_set_ = 1; + h = gethostbyname (w2); + if (h != NULL) { + printf("Login server binding IP address : %s -> %d.%d.%d.%d\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + sprintf(bind_ip_str, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + } else + memcpy(bind_ip_str,w2,16); + } else if(strcmpi(w1,"login_port")==0){ login_port=atoi(w2); printf ("set login_port : %s\n",w2); } @@ -731,15 +1645,7 @@ int login_config_read(const char *cfgName){ else if(strcmpi(w1,"dynamic_pass_failure_ban_how_long")==0){ dynamic_pass_failure_ban_how_long=atoi(w2); printf ("set dynamic_pass_failure_ban_how_long : %d\n",dynamic_pass_failure_ban_how_long); - } - else if(strcmpi(w1,"anti_freeze_enable")==0){ - anti_freeze_enable = config_switch(w2); - } - else if (strcmpi(w1, "anti_freeze_interval") == 0) { - ANTI_FREEZE_INTERVAL = atoi(w2); - if (ANTI_FREEZE_INTERVAL < 5) - ANTI_FREEZE_INTERVAL = 5; // minimum 5 seconds - } + } else if (strcmpi(w1, "import") == 0) { login_config_read(w2); } else if(strcmpi(w1,"imalive_on")==0) { //Added by Mugendai for I'm Alive mod @@ -750,8 +1656,19 @@ int login_config_read(const char *cfgName){ flush_on = atoi(w2); //Added by Mugendai for GUI } else if(strcmpi(w1,"flush_time")==0) { //Added by Mugendai for GUI flush_time = atoi(w2); //Added by Mugendai for GUI - } - else if(strcmpi(w1,"use_MD5_passwords")==0){ + } else if(strcmpi(w1, "new_account") == 0){ //Added by Sirius for new account _M/_F + new_account_flag = atoi(w2); //Added by Sirius for new account _M/_F + } else if(strcmpi(w1, "check_client_version") == 0){ //Added by Sirius for client version check + //check_client_version = config_switch(w2); //Added by Sirius for client version check + if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 ){ + check_client_version = 1; + } + if(strcmpi(w2,"off") == 0 || strcmpi(w2,"no") == 0 ){ + check_client_version = 0; + } + } else if(strcmpi(w1, "client_version_to_connect") == 0){ //Added by Sirius for client version check + client_version_to_connect = atoi(w2); //Added by SIrius for client version check + } else if(strcmpi(w1,"use_MD5_passwords")==0){ if (!strcmpi(w2,"yes")) { use_md5_passwds=1; } else if (!strcmpi(w2,"no")){ @@ -785,15 +1702,21 @@ int login_config_read(const char *cfgName){ if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 ) console = 1; } + else if (strcmpi(w1, "case_sensitive") == 0) { + if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 ) + case_sensitive = 1; + if(strcmpi(w2,"off") == 0 || strcmpi(w2,"no") == 0 ) + case_sensitive = 0; + } + else if(strcmpi(w1, "register_users_online") == 0) { + register_users_online = config_switch(w2); + } } fclose(fp); - printf ("End reading login configuration...\n"); + printf ("End reading configuration...\n"); return 0; } -//----------------------------------------------------- -// SQL configuration -//----------------------------------------------------- void sql_config_read(const char *cfgName){ /* Kalaspuff, to get login_db */ int i; char line[1024], w1[1024], w2[1024]; @@ -802,7 +1725,7 @@ void sql_config_read(const char *cfgName){ /* Kalaspuff, to get login_db */ printf("file not found: %s\n",cfgName); exit(1); } - printf("Start reading SQL configuration: %s\n", cfgName); + printf("reading configure: %s\n", cfgName); while(fgets(line, sizeof(line)-1, fp)){ if(line[0] == '/' && line[1] == '/') continue; @@ -850,16 +1773,13 @@ void sql_config_read(const char *cfgName){ /* Kalaspuff, to get login_db */ else if (strcmpi(w1, "loginlog_db") == 0) { strcpy(loginlog_db, w2); } - else if(strcmpi(w1,"lowest_gm_level")==0){ - lowest_gm_level = atoi(w2); - } //support the import command, just like any other config else if(strcmpi(w1,"import")==0){ sql_config_read(w2); } - } - fclose(fp); - printf("reading SQL configuration done.....\n"); + } + fclose(fp); + printf("reading configure done.....\n"); } @@ -882,64 +1802,67 @@ int flush_timer(int tid, unsigned int tick, int id, int data){ return 0; } +//-------------------------------------- +// Function called at exit of the server +//-------------------------------------- +static int online_db_final(void *key,void *data,va_list ap) +{ + int *p = (int *) data; + if (p) aFree(p); + return 0; +} +void do_final(void) { + //sync account when terminating. + //but no need when you using DBMS (mysql) + mmo_db_close(); + numdb_final(online_db, online_db_final); + exit_dbn(); + timer_final(); +} + int do_init(int argc,char **argv){ + //initialize login server int i; - //read login configuration + SERVER_TYPE = SERVER_LOGIN; + //read login configue login_config_read( (argc>1)?argv[1]:LOGIN_CONF_NAME ); - - //read SQL configuration sql_config_read(SQL_CONF_NAME); - - //read LAN support configuation login_lan_config_read((argc > 1) ? argv[1] : LAN_CONF_NAME); - //Generate Passworded Key. - #ifdef DEBUG - printf ("memset value: [0] var: [md5key] \n"); - #endif - + printf ("memset md5key \n"); memset(md5key, 0, sizeof(md5key)); - - #ifdef DEBUG - printf ("memset var: [md5key] complete\n"); - printf ("Set MD5 key length\n"); - #endif - + printf ("memset md5key complete\n"); + printf ("memset keyleng\n"); md5keylen=rand()%4+12; for(i=0;i<md5keylen;i++) md5key[i]=rand()%255+1; + printf ("memset keyleng complete\n"); - #ifdef DEBUG - printf ("Set MD5 key length complete\n"); - printf ("Set Auth FIFO Size\n"); - #endif - + printf ("set FIFO Size\n"); for(i=0;i<AUTH_FIFO_SIZE;i++) auth_fifo[i].delflag=1; + printf ("set FIFO Size complete\n"); - #ifdef DEBUG - printf ("Set Auth FIFO Size complete\n"); - printf ("Set max number servers\n"); - #endif - + printf ("set max servers\n"); for(i=0;i<MAX_SERVERS;i++) server_fd[i]=-1; - - #ifdef DEBUG - printf ("Set max number servers complete\n"); - #endif - + printf ("set max servers complete\n"); //server port open & binding - login_fd=make_listen_port(login_port); + if (bind_ip_str[0] != '\0') + bind_ip = inet_addr(bind_ip_str); + else + bind_ip = INADDR_ANY; - printf ("Initializing SQL DB\n"); - mmo_auth_sqldb_init(); - printf ("SQL DB Initialized\n"); + //login_fd=make_listen_port(login_port); + login_fd=make_listen_bind(bind_ip,login_port); - // Close connection to SQL DB at termiantion - set_termfunc(mmo_db_close); + //Auth start + printf ("Running mmo_auth_sqldb_init()\n"); + mmo_auth_sqldb_init(); + printf ("finished mmo_auth_sqldb_init()\n"); + set_termfunc(do_final); //set default parser as parse_login function set_defaultparse(parse_login); @@ -952,15 +1875,8 @@ int do_init(int argc,char **argv){ if(flush_on) add_timer_interval(gettick()+10, flush_timer,0,0,flush_time); - if(anti_freeze_enable > 0) { - add_timer_func_list(char_anti_freeze_system, "char_anti_freeze_system"); - i = add_timer_interval(gettick()+1000, char_anti_freeze_system, 0, 0, ANTI_FREEZE_INTERVAL * 1000); - } - // ban deleter timer - 1 minute term - #ifdef DEBUG - printf("add interval tic (ip_ban_check)...\n"); - #endif + printf("add interval tic (ip_ban_check)....\n"); i=add_timer_interval(gettick()+10, ip_ban_check,0,0,60*1000); if (console) { @@ -969,10 +1885,12 @@ int do_init(int argc,char **argv){ } // Online user database init - free(online_db); + aFree(online_db); online_db = numdb_init(); printf("The login-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n", login_port); return 0; } + + diff --git a/src/login_sql/login.h b/src/login_sql/login.h index 075284450..725c02ada 100644 --- a/src/login_sql/login.h +++ b/src/login_sql/login.h @@ -15,126 +15,19 @@ #define START_ACCOUNT_NUM 2000000 #define END_ACCOUNT_NUM 100000000 -//add include for DBMS(mysql) -#include <mysql.h> - -#include "../common/socket.h" -#include "../common/core.h" -#include "../common/mmo.h" -#include "../common/version.h" -#include "../common/db.h" -#include "../common/timer.h" -#include "../common/nullpo.h" - -#include "strlib.h" - -#ifdef LCCWIN32 -#include <winsock.h> -#pragma lib <libmysql.lib> -extern void gettimeofday(struct timeval *t, struct timezone *dummy); -#else -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <winsock2.h> -#include <time.h> -void Gettimeofday(struct timeval *timenow) -{ - time_t t; - t = clock(); - timenow->tv_usec = t; - timenow->tv_sec = t / CLK_TCK; - return; -} -#define gettimeofday(timenow, dummy) Gettimeofday(timenow) -#pragma comment(lib,"libmysql.lib") -#else -#include <sys/socket.h> -#include <netinet/in.h> -#include <sys/time.h> -#include <sys/ioctl.h> -#include <arpa/inet.h> -#include <unistd.h> -#endif -#endif - -// Auth Data -#define AUTH_FIFO_SIZE 256 -extern struct auth_fifo { - int account_id,login_id1,login_id2; - int ip,sex,delflag; -} auth_fifo[AUTH_FIFO_SIZE]; - -extern int auth_fifo_pos; - -// MySQL Query -extern char tmpsql[65535], prev_query[65535]; - -// MySQL Connection Handle -extern MYSQL mysql_handle; -extern MYSQL_RES* sql_res ; -extern MYSQL_ROW sql_row ; - -// MySQL custom table and column names -extern char login_db[32]; -extern char loginlog_db[32]; -extern char login_db_account_id[32]; -extern char login_db_userid[32]; -extern char login_db_user_pass[32]; -extern char login_db_level[32]; - -// MD5 Key Data for encrypted login -extern int md5keylen; -extern char md5key[20]; - -// Dynamic IP Ban config -extern int ipban; -extern int dynamic_account_ban; -extern int dynamic_account_ban_class; -extern int dynamic_pass_failure_ban; -extern int dynamic_pass_failure_ban_time; -extern int dynamic_pass_failure_ban_how_many; -extern int dynamic_pass_failure_ban_how_long; - -// Date format for bans -extern char date_format[32]; - -// minimum level of player/GM (0: player, 1-99: gm) to connect on the server -extern int min_level_to_connect; - -// It's to check IP of a player between login-server and char-server (part of anti-hacking system) -extern int check_ip_flag; - -// Login's FD -extern int login_fd; - -// LAN IP of char-server and subnet mask(Kashy) -extern char lan_char_ip[16]; -extern int subnetmaski[4]; - -// Char-server data -extern struct mmo_char_server server[MAX_SERVERS]; -extern int server_fd[MAX_SERVERS]; -extern unsigned char servers_connected; - -// Anti-freeze Data -extern int server_freezeflag[MAX_SERVERS]; -extern int anti_freeze_enable; -extern int ANTI_FREEZE_INTERVAL; - struct mmo_account { + int version; //Added by sirius for versioncheck char* userid; char* passwd; int passwdenc; - + + long account_id; long login_id1; long login_id2; long char_id; char lastlogin[24]; int sex; - - time_t ban_until_time; }; struct mmo_char_server { @@ -143,17 +36,8 @@ struct mmo_char_server { short port; int users; int maintenance; - int new; + int new_; }; -void sql_query(char*,char*); -int e_mail_check(unsigned char*); -void add_online_user(int); -int is_user_online(int); -void remove_online_user(int); -int mmo_auth( struct mmo_account*, int); -unsigned char isGM(int); -int lan_ip_check(unsigned char *); - #endif diff --git a/src/login_sql/login_int.c b/src/login_sql/login_int.c deleted file mode 100644 index 4a3220521..000000000 --- a/src/login_sql/login_int.c +++ /dev/null @@ -1,376 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <time.h> -#include <signal.h> -#include <fcntl.h> -#include <string.h> - -#include "login.h" -#include "char_int.h" - -//---------------------- -// Client requesting login [Edit: Wizputer] -//---------------------- -int client_request_login(int fd,int len,unsigned char *p ) { - if(len < ((RFIFOW(fd, 0) ==0x64)?55:47)) - return -1; - - struct mmo_account account; - char t_uid[32]; - int server_num = 0,result,i; - - if( !servers_connected) { - WFIFOW(fd,0) = 0x81; - WFIFOL(fd,2) = 1; // 01 = Server closed - WFIFOSET(fd,3); - } - - #ifdef DEBUG - printf("client connection request %s from %d.%d.%d.%d\n", RFIFOP(fd, 6), p[0], p[1], p[2], p[3]); - #endif - - account.userid = RFIFOP(fd, 6); - account.passwd = RFIFOP(fd, 30); -#ifdef PASSWORDENC - account.passwdenc= (RFIFOW(fd,0)==0x64)?0:PASSWORDENC; -#else - account.passwdenc=0; -#endif - result=mmo_auth(&account, fd); - - jstrescapecpy(t_uid,RFIFOP(fd, 6)); - if(result==-1){ - unsigned char gm_level = isGM(account.account_id); - if (min_level_to_connect > gm_level || !servers_connected) { - WFIFOW(fd,0) = 0x81; - WFIFOL(fd,2) = 1; // 01 = Server closed - WFIFOSET(fd,3); - } else { - if (p[0] != 127) { - sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s','100', 'login ok')", loginlog_db, p[0], p[1], p[2], p[3], t_uid); - sql_query(tmpsql,"client_request_login"); - } - - if (gm_level) { - #ifdef DEBUG - printf("Connection of the GM (level:%d) account '%s' accepted.\n", gm_level, account.userid); - #endif - } else { - #ifdef DEBUG - printf("Connection of the account '%s' accepted.\n", account.userid); - #endif - } - - for(i = 0; i < MAX_SERVERS || server_num < servers_connected ; i++) - if (server_fd[i] >= 0) { - //Lan check added by Kashy - if (lan_ip_check(p)) - WFIFOL(fd,47+server_num*32) = inet_addr(lan_char_ip); - else - WFIFOL(fd,47+server_num*32) = server[i].ip; - - WFIFOW(fd,47+server_num*32+4) = server[i].port; - memcpy(WFIFOP(fd,47+server_num*32+6), server[i].name, 20); - WFIFOW(fd,47+server_num*32+26) = server[i].users; - WFIFOW(fd,47+server_num*32+28) = server[i].maintenance; - WFIFOW(fd,47+server_num*32+30) = server[i].new; - server_num++; - } - - WFIFOW(fd,0)=0x69; - WFIFOW(fd,2)=47+32*server_num; - WFIFOL(fd,4)=account.login_id1; - WFIFOL(fd,8)=account.account_id; - WFIFOL(fd,12)=account.login_id2; - WFIFOL(fd,16)=0; - memcpy(WFIFOP(fd,20),account.lastlogin,24); - WFIFOB(fd,46)=account.sex; - WFIFOSET(fd,47+32*server_num); - - if(auth_fifo_pos>=AUTH_FIFO_SIZE) - auth_fifo_pos=0; - - auth_fifo[auth_fifo_pos].account_id=account.account_id; - auth_fifo[auth_fifo_pos].login_id1=account.login_id1; - auth_fifo[auth_fifo_pos].login_id2=account.login_id2; - auth_fifo[auth_fifo_pos].sex=account.sex; - auth_fifo[auth_fifo_pos].delflag=0; - auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr; - auth_fifo_pos++; - } - } else { - char error[32]; - - sprintf(tmpsql,"SELECT `error` FROM `errors` WHERE `result`='%d'",result); - sql_query(tmpsql,"client_request_login"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { - if ((sql_row = mysql_fetch_row(sql_res))) { - sprintf(error,sql_row[0]); - } else { - sprintf(error,"No Error!"); - } - } - - - sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s', '%d','login failed : %s')", loginlog_db, p[0], p[1], p[2], p[3], t_uid, result, error); - - - sql_query(tmpsql,"client_request_login"); - - if ((result == 1) && (dynamic_pass_failure_ban != 0)){ // failed password - sprintf(tmpsql,"SELECT count(*) FROM `%s` WHERE `ip` = '%d.%d.%d.%d' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE", - loginlog_db, p[0], p[1], p[2], p[3], dynamic_pass_failure_ban_time); //how many times filed account? in one ip. - sql_query(tmpsql,"client_request_login"); - - if ((sql_res = mysql_store_result(&mysql_handle))) { - if ((sql_row = mysql_fetch_row(sql_res))) { - if (atoi(sql_row[0]) >= dynamic_pass_failure_ban_how_many ) { - sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban: %s')", p[0], p[1], p[2], dynamic_pass_failure_ban_how_long, t_uid); - sql_query(tmpsql,"client_request_login"); - } - } - } - - - mysql_free_result(sql_res); - - } - - //cannot connect login failed - memset(WFIFOP(fd,0),'\0',23); - WFIFOW(fd,0)=0x6a; - WFIFOB(fd,2)=result-1; - if (result == 6) { // 6 = Your are Prohibited to log in until %s - char tmpstr[256]; - strftime(tmpstr, 20, date_format, localtime(&account.ban_until_time)); - tmpstr[19] = '\0'; - memcpy(WFIFOP(fd,3), tmpstr, 20); - } else { // we send error message - memcpy(WFIFOP(fd,3), error, 20); - } - } - - WFIFOSET(fd,23); - - RFIFOSKIP(fd,(RFIFOW(fd,0)==0x64)?55:47); - - return 0; -} - -//------------------------------------------------------ -// MD5 Key requested for encypted login [Edit: Wizputer -//------------------------------------------------------ -int md5_key_request(int fd, int len) { - if (session[fd]->session_data) { - #ifdef DEBUG - printf("login: abnormal request of MD5 key (already opened session).\n"); - #endif - session[fd]->eof = 1; - return -1; - } - - #ifdef DEBUG - printf("Request Password key -%s\n",md5key); - #endif - - RFIFOSKIP(fd,2); - WFIFOW(fd,0)=0x01dc; - WFIFOW(fd,2)=4+md5keylen; - memcpy(WFIFOP(fd,4),md5key,md5keylen); - WFIFOSET(fd,WFIFOW(fd,2)); - - return 0; -} - -//---------------------------------------------------- -// Char-server requesting connection [Edit: Wizputer] -//----------------------------------------------------- -int char_request_login(int fd, int len, unsigned char *p) { - if(len<86) - return -1; - - struct mmo_account account; - unsigned char* server_name; - char t_uid[32]; - int result; - - sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s@%s','100', 'charserver - %s@%d.%d.%d.%d:%d')", loginlog_db, p[0], p[1], p[2], p[3], RFIFOP(fd, 2),RFIFOP(fd, 60),RFIFOP(fd, 60), RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58)); - sql_query(tmpsql,"char_request_login"); - - #ifdef DEBUG - printf("server connection request %s @ %d.%d.%d.%d:%d (%d.%d.%d.%d)\n", - RFIFOP(fd, 60), RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58), - p[0], p[1], p[2], p[3]); - #endif - - account.userid = RFIFOP(fd, 2); - account.passwd = RFIFOP(fd, 26); - account.passwdenc = 0; - server_name = RFIFOP(fd,60); - result = mmo_auth(&account, fd); - - #ifdef DEBUG - printf("Result: %d - Sex: %d - Account ID: %d\n",result,account.sex,(int) account.account_id); - #endif - - if(result == -1 && account.sex==2 && account.account_id<MAX_SERVERS && server_fd[account.account_id]==-1){ - printf("Connection of the char-server '%s' accepted.\n", server_name); - - memset(&server[account.account_id], 0, sizeof(struct mmo_char_server)); - - server[account.account_id].ip=RFIFOL(fd,54); - server[account.account_id].port=RFIFOW(fd,58); - memcpy(server[account.account_id].name,RFIFOP(fd,60),20); - server[account.account_id].users=0; - server[account.account_id].maintenance=RFIFOW(fd,82); - server[account.account_id].new=RFIFOW(fd,84); - server_fd[account.account_id]=fd; - - if(anti_freeze_enable) - server_freezeflag[account.account_id] = 5; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed - - jstrescapecpy(t_uid,server[account.account_id].name); - - sprintf(tmpsql,"REPLACE DELAYED INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%ld', '%s', '%d')", - account.account_id, server[account.account_id].name,0); - sql_query(tmpsql,"char_request_login"); - - WFIFOW(fd,0)=0x2711; - WFIFOB(fd,2)=0; - WFIFOSET(fd,3); - session[fd]->func_parse=parse_fromchar; - realloc_fifo(fd,FIFOSIZE_SERVERLINK,FIFOSIZE_SERVERLINK); - - servers_connected++; - } else { - WFIFOW(fd, 0) =0x2711; - WFIFOB(fd, 2)=3; - WFIFOSET(fd, 3); - } - - RFIFOSKIP(fd, 86); - - return 0; -} - -//--------------------------------------------- -// Athena Version Info Request [Edit: Wizputer] -//--------------------------------------------- -int request_athena_info(int fd, int len) { - #ifdef DEBUG - printf ("Athena version check...\n"); - #endif - - WFIFOW(fd,0)=0x7531; - WFIFOB(fd,2)=ATHENA_MAJOR_VERSION; - WFIFOB(fd,3)=ATHENA_MINOR_VERSION; - WFIFOB(fd,4)=ATHENA_REVISION; - WFIFOB(fd,5)=ATHENA_RELEASE_FLAG; - WFIFOB(fd,6)=ATHENA_OFFICIAL_FLAG; - WFIFOB(fd,7)=ATHENA_SERVER_LOGIN; - WFIFOW(fd,8)=ATHENA_MOD_VERSION; - WFIFOSET(fd,10); - RFIFOSKIP(fd,2); - - return 0; -} - -//---------------------------------------------------------------------------------------- -// Default packet parsing (normal players or administation/char-server connection requests) -//---------------------------------------------------------------------------------------- -int parse_login(int fd) { - char ip[16]; - int len,res=0; - - unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr; - sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - - if (ipban > 0) { - //ip ban - //p[0], p[1], p[2], p[3] - //request DB connection - //check - sprintf(tmpsql, "SELECT count(*) FROM `ipbanlist` WHERE `list` = '%d.*.*.*' OR `list` = '%d.%d.*.*' OR `list` = '%d.%d.%d.*' OR `list` = '%d.%d.%d.%d'", - p[0], p[0], p[1], p[0], p[1], p[2], p[0], p[1], p[2], p[3]); - sql_query(tmpsql,"parse_login"); - - if((sql_res = mysql_store_result(&mysql_handle))) { - if((sql_row = mysql_fetch_row(sql_res))) {//row fetching - if (atoi(sql_row[0]) >0) { - // ip ban ok. - printf ("packet from banned ip : %d.%d.%d.%d" RETCODE, p[0], p[1], p[2], p[3]); - - sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', 'unknown','-3', 'ip banned')", loginlog_db, p[0], p[1], p[2], p[3]); - sql_query(tmpsql,"parse_login"); - - #ifdef DEBUG - printf ("close session connection...\n"); - #endif - - // close connection - session[fd]->eof = 1; - } else { - #ifdef DEBUG - printf ("packet from ip (ban check ok) : %d.%d.%d.%d" RETCODE, p[0], p[1], p[2], p[3]); - #endif - } - } - } - - mysql_free_result(sql_res); - } - - if (session[fd]->eof) { - int i; - for(i = 0; i < MAX_SERVERS && i < servers_connected; i++) - if (server_fd[i] == fd) { - server_fd[i] = -1; - servers_connected--; - } - close(fd); - delete_session(fd); - return 0; - } - - len = RFIFOREST(fd); - - while(len>=2 && res == 0){ - #ifdef DEBUG_PACKETS - printf("parse_login : %d %d packet case=%x\n", fd, RFIFOREST(fd), RFIFOW(fd,0)); - #endif - - switch(RFIFOW(fd,0)){ - case 0x200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive. - if (RFIFOREST(fd) < 26) - return 0; - RFIFOSKIP(fd,26); - break; - - case 0x204: // New alive packet: structure: 0x204 <encrypted.account.userid>.16B. (new ragexe from 22 june 2004) - if (RFIFOREST(fd) < 18) - return 0; - RFIFOSKIP(fd,18); - break; - - case 0x64: - case 0x01dd: res = client_request_login(fd,len,p); break; - case 0x01db: res = md5_key_request(fd,len); break; - case 0x2710: res = char_request_login(fd,len,p); break; - case 0x7530: res = request_athena_info(fd,len); break; - - case 0x7532: - default: - #ifdef DEBUG - printf ("End of connection (ip: %s)" RETCODE, ip); - #endif - session[fd]->eof = 1; - return 0; - } - - len = RFIFOREST(fd); - } - - return 0; -} - diff --git a/src/login_sql/login_int.h b/src/login_sql/login_int.h deleted file mode 100644 index 712585616..000000000 --- a/src/login_sql/login_int.h +++ /dev/null @@ -1 +0,0 @@ -int parse_login(int); diff --git a/src/login_sql/md5calc.c b/src/login_sql/md5calc.c index 58cea1246..856c7ecb0 100644 --- a/src/login_sql/md5calc.c +++ b/src/login_sql/md5calc.c @@ -95,7 +95,7 @@ static void MD5_Round_Calculate(const unsigned char *block, //Save A as AA, B as BB, C as CC, and and D as DD (saving of A, B, C, and D) unsigned int A=*A2, B=*B2, C=*C2, D=*D2; unsigned int AA = A,BB = B,CC = C,DD = D; - + //It is a large region variable reluctantly because of calculation of a round. . . for Round1...4 pX = X; @@ -186,7 +186,7 @@ void MD5_String2binary(const char * string, char * output) memset(padding_message+copy_len, 0, 64 - copy_len); //It buries by 0 until it becomes extended bit length. padding_message[copy_len] |= 0x80; //The next of a message is 1. - //1-4 + //1-4 //If 56 bytes or more (less than 64 bytes) of remainder becomes, it will calculate by extending to 64 bytes. if (56 <= copy_len) { MD5_Round_Calculate(padding_message, A,B,C,D); @@ -225,7 +225,7 @@ void MD5_String(const char * string, char * output) { unsigned char digest[16]; - MD5_String2binary(string,digest); + MD5_String2binary(string,(char*)digest); sprintf(output, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", digest[ 0], digest[ 1], digest[ 2], digest[ 3], diff --git a/src/login_sql/strlib.c b/src/login_sql/strlib.c deleted file mode 100644 index fd8c90ef0..000000000 --- a/src/login_sql/strlib.c +++ /dev/null @@ -1,58 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "strlib.h" -#include "utils.h" - -//----------------------------------------------- -// string lib. -unsigned char* jstrescape (unsigned char* pt) { - //copy from here - unsigned char * ptr; - int i =0, j=0; - - //copy string to temporary - CREATE(ptr, char, J_MAX_MALLOC_SIZE); - strcpy (ptr,pt); - - while (ptr[i] != '\0') { - switch (ptr[i]) { - case '\'': - pt[j++] = '\\'; - pt[j++] = ptr[i++]; - break; - case '\\': - pt[j++] = '\\'; - pt[j++] = ptr[i++]; - break; - default: - pt[j++] = ptr[i++]; - } - } - pt[j++] = '\0'; - if(ptr) free(ptr); - return (unsigned char*) &pt[0]; -} - -unsigned char* jstrescapecpy (unsigned char* pt,unsigned char* spt) { - //copy from here - int i =0, j=0; - - while (spt[i] != '\0') { - switch (spt[i]) { - case '\'': - pt[j++] = '\\'; - pt[j++] = spt[i++]; - break; - case '\\': - pt[j++] = '\\'; - pt[j++] = spt[i++]; - break; - default: - pt[j++] = spt[i++]; - } - } - pt[j++] = '\0'; - return (unsigned char*) &pt[0]; -} diff --git a/src/map/GNUmakefile b/src/map/GNUmakefile deleted file mode 100644 index 03f520f37..000000000 --- a/src/map/GNUmakefile +++ /dev/null @@ -1,75 +0,0 @@ -all: txt sql - -txt: txtobj map-server - -sql: sqlobj map-server_sql - -txtobj: - mkdir txtobj - -sqlobj: - mkdir sqlobj - -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/grfio.o ../common/db.o ../common/lock.o ../common/nullpo.o ../common/malloc.o ../common/showmsg.o -LIBS = -lz -lm - -map-server: txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/npc.o txtobj/chat.o txtobj/path.o txtobj/itemdb.o txtobj/mob.o txtobj/script.o txtobj/storage.o txtobj/skill.o txtobj/atcommand.o txtobj/charcommand.o txtobj/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o $(COMMON_OBJ) - $(CC) -o ../../$@ $^ $(LIBS) - -map-server_sql: sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/npc.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/charcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/mail.o sqlobj/log.o $(COMMON_OBJ) - $(CC) -o ../../$@ $^ $(LIB_S) - -txtobj/%.o: %.c - $(COMPILE.c) -DTXT_ONLY $(OUTPUT_OPTION) $< - -sqlobj/%.o: %.c - $(COMPILE.c) $(OUTPUT_OPTION) $< - -txtobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h ../common/core.h ../common/timer.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -txtobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/showmsg.h -txtobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h -txtobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h -txtobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h -txtobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -txtobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h ../common/timer.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -txtobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h ../common/timer.h ../common/socket.h ../common/db.h ../common/mmo.h ../common/lock.h ../common/showmsg.h -txtobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h ../common/mmo.h ../common/db.h ../common/showmsg.h -txtobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -txtobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h ../common/mmo.h ../common/showmsg.h -txtobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h ../common/mmo.h ../common/showmsg.h -txtobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h - -sqlobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h log.h ../common/core.h ../common/timer.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -sqlobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/showmsg.h -sqlobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h -sqlobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h -sqlobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h -sqlobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -sqlobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h log.h ../common/timer.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -sqlobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h ../common/timer.h ../common/socket.h ../common/db.h ../common/mmo.h ../common/lock.h ../common/showmsg.h -sqlobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h ../common/mmo.h ../common/db.h ../common/showmsg.h -sqlobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h log.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -sqlobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h log.h ../common/mmo.h ../common/showmsg.h -sqlobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h log.h ../common/mmo.h ../common/showmsg.h -sqlobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/mail.o: mail.c mail.h ../common/showmsg.h -sqlobj/log.o: log.c log.h map.h ../common/nullpo.h -sqlobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h - -clean: - rm -rf *.o ../../map-server ../../map-server_sql sqlobj txtobj diff --git a/src/map/Makefile b/src/map/Makefile index 4786887ae..b413c8a62 100644 --- a/src/map/Makefile +++ b/src/map/Makefile @@ -10,13 +10,15 @@ txtobj: sqlobj: mkdir sqlobj -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/grfio.o ../common/db.o ../common/lock.o ../common/nullpo.o ../common/malloc.o ../common/showmsg.o +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/grfio.o ../common/obj/db.o ../common/obj/lock.o ../common/obj/nullpo.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o ../common/obj/strlib.o + +COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/grfio.h ../common/db.h ../common/lock.h ../common/nullpo.h ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h LIBS = -lz -lm -map-server: txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/npc.o txtobj/chat.o txtobj/path.o txtobj/itemdb.o txtobj/mob.o txtobj/script.o txtobj/storage.o txtobj/skill.o txtobj/atcommand.o txtobj/charcommand.o txtobj/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o $(COMMON_OBJ) - $(CC) -o ../../$@ $> $(LIBS) +map-server: txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/status.o txtobj/npc.o txtobj/npc_chat.o txtobj/chat.o txtobj/path.o txtobj/itemdb.o txtobj/mob.o txtobj/script.o txtobj/storage.o txtobj/skill.o txtobj/atcommand.o txtobj/charcommand.o txtobj/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o txtobj/log.o $(COMMON_OBJ) + $(CC) -o ../../$@ $> $(LIBS) $(LIB_S) -map-server_sql: sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/npc.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/charcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/mail.o sqlobj/log.o $(COMMON_OBJ) +map-server_sql: sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/status.o sqlobj/npc.o sqlobj/npc_chat.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/charcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/mail.o sqlobj/log.o $(COMMON_OBJ) $(CC) -o ../../$@ $> $(LIB_S) txtobj/%.o: %.c @@ -25,51 +27,56 @@ txtobj/%.o: %.c sqlobj/%.o: %.c $(COMPILE.c) $(OUTPUT_OPTION) $< -txtobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h ../common/core.h ../common/timer.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -txtobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/showmsg.h -txtobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h -txtobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h -txtobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h -txtobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -txtobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h ../common/timer.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -txtobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h ../common/timer.h ../common/socket.h ../common/db.h ../common/mmo.h ../common/lock.h ../common/showmsg.h -txtobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h ../common/mmo.h ../common/db.h ../common/showmsg.h -txtobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -txtobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h ../common/mmo.h ../common/showmsg.h -txtobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h ../common/mmo.h ../common/showmsg.h -txtobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h +txtobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h $(COMMON_H) +txtobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_H) +txtobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h $(COMMON_H) +txtobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h $(COMMON_H) +txtobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h $(COMMON_H) +txtobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +txtobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +txtobj/chat.o: chat.c map.h clif.h pc.h chat.h $(COMMON_H) +txtobj/path.o: path.c map.h battle.h $(COMMON_H) +txtobj/itemdb.o: itemdb.c map.h battle.h itemdb.h $(COMMON_H) +txtobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h $(COMMON_H) +txtobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h $(COMMON_H) +txtobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h $(COMMON_H) +txtobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h $(COMMON_H) +txtobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) +txtobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h $(COMMON_H) +txtobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h $(COMMON_H) +txtobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h $(COMMON_H) +txtobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h $(COMMON_H) +txtobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h $(COMMON_H) +txtobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h $(COMMON_H) +txtobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h $(COMMON_H) +txtobj/log.o: log.c log.h map.h $(COMMON_H) +txtobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) -sqlobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h log.h ../common/core.h ../common/timer.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -sqlobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/showmsg.h -sqlobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h -sqlobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h -sqlobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h -sqlobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -sqlobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h log.h ../common/timer.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -sqlobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h ../common/timer.h ../common/socket.h ../common/db.h ../common/mmo.h ../common/lock.h ../common/showmsg.h -sqlobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h ../common/mmo.h ../common/db.h ../common/showmsg.h -sqlobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h log.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -sqlobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h log.h ../common/mmo.h ../common/showmsg.h -sqlobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h log.h ../common/mmo.h ../common/showmsg.h -sqlobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/mail.o: mail.c mail.h ../common/showmsg.h -sqlobj/log.o: log.c log.h map.h ../common/nullpo.h -sqlobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h +sqlobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h log.h $(COMMON_H) +sqlobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_H) +sqlobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h $(COMMON_H) +sqlobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h $(COMMON_H) +sqlobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h $(COMMON_H) +sqlobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +sqlobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +sqlobj/chat.o: chat.c map.h clif.h pc.h chat.h $(COMMON_H) +sqlobj/path.o: path.c map.h battle.h $(COMMON_H) +sqlobj/itemdb.o: itemdb.c map.h battle.h itemdb.h $(COMMON_H) +sqlobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h log.h $(COMMON_H) +sqlobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h $(COMMON_H) +sqlobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h $(COMMON_H) +sqlobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h log.h $(COMMON_H) +sqlobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) +sqlobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h $(COMMON_H) +sqlobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h $(COMMON_H) +sqlobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h log.h $(COMMON_H) +sqlobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h $(COMMON_H) +sqlobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h log.h $(COMMON_H) +sqlobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h $(COMMON_H) +sqlobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h $(COMMON_H) +sqlobj/mail.o: mail.c mail.h $(COMMON_H) +sqlobj/log.o: log.c log.h map.h $(COMMON_H) +sqlobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) clean: rm -rf *.o ../../map-server ../../map-server_sql sqlobj txtobj diff --git a/src/map/Makefile.win32 b/src/map/Makefile.win32 index ed4b4e95a..2fa1861ac 100644 --- a/src/map/Makefile.win32 +++ b/src/map/Makefile.win32 @@ -15,25 +15,28 @@ txtobj: sqlobj: mkdir sqlobj -ZLIBDIR = C:/eathena/zlib122 -PACKETDEF = -DPACKETVER=5 -DNEW_006b -D__WIN32 +ZLIBDIR = ../zlib +PACKETDEF = -DPACKETVER=6 -DNEW_006b -D__WIN32 -DLOCALZLIB # OPT = /MDd /D_DEBUG OPT = LINKOPT = /debug /SUBSYSTEM:CONSOLE # OPT = /O2 CFLAGS = $(OPT) /nologo /I../common /I$(ZLIBDIR) $(PACKETDEF) /D_WIN32 -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/grfio.o ../common/db.o ../common/lock.o ../common/nullpo.o ../common/malloc.o ../common/showmsg.o +COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/grfio.o ../common/db.o ../common/lock.o ../common/nullpo.o ../common/malloc.o ../common/showmsg.o ../common/strlib.o ../common/utils.o + LIBS = "WSOCK32.LIB" # "WSOCK32.LIB" "USER32.LIB" "ADVAPI32.LIB" "MSVCRT.LIB" "OLDNAMES.LIB" "KERNEL32.LIB" -TXTOBJS = txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/npc.o txtobj/chat.o txtobj/path.o txtobj/itemdb.o txtobj/mob.o txtobj/script.o txtobj/storage.o txtobj/skill.o txtobj/atcommand.o txtobj/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o $(COMMON_OBJ) $(ZLIBDIR)/inflate.o $(ZLIBDIR)/adler32.o $(ZLIBDIR)/crc32.o $(ZLIBDIR)/inftrees.o $(ZLIBDIR)/zutil.o $(ZLIBDIR)/inffast.o +TXTOBJS = txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/status.o txtobj/npc.o txtobj/npc_chat.o txtobj/chat.o txtobj/path.o txtobj/itemdb.o txtobj/mob.o txtobj/script.o txtobj/storage.o txtobj/skill.o txtobj/atcommand.o txtobj/charcommand.o txtobj/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o txtobj/log.o $(COMMON_OBJ) $(ZLIBDIR)/inflate.o $(ZLIBDIR)/deflate.o $(ZLIBDIR)/trees.o $(ZLIBDIR)/adler32.o $(ZLIBDIR)/compress.o $(ZLIBDIR)/crc32.o $(ZLIBDIR)/inftrees.o $(ZLIBDIR)/zutil.o $(ZLIBDIR)/inffast.o + +SQLOBJS = sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/status.o sqlobj/npc.o sqlobj/npc_chat.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/charcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/log.o $(COMMON_OBJ) $(ZLIBDIR)/inflate.o $(ZLIBDIR)/adler32.o $(ZLIBDIR)/crc32.o $(ZLIBDIR)/inftrees.o $(ZLIBDIR)/zutil.o $(ZLIBDIR)/inffast.o map-server: $(TXTOBJS) link $(LINKOPT) /out:../../$@.exe $(TXTOBJS) $(LIBS) -map-server_sql: sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/npc.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/mail.o $(COMMON_OBJ) +map-server_sql: $(SQLOBJS) link $(LINKOPT) /out:../../$@.exe $> $(LIBS) txtobj/%.o: %.c @@ -86,7 +89,7 @@ sqlobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h ../common/db. sqlobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h log.h ../common/mmo.h ../common/showmsg.h sqlobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h sqlobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/mail.o: mail.c mail.h ../common/showmsg.h +sqlobj/mail.o: mail.c mail.h ../common/showmsg.h ../common/strlib.h ../common/utils.h sqlobj/log.o: log.c log.h map.h ../common/nullpo.h clean: diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 34bf0150d..79e3ec675 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -8,6 +8,9 @@ #include "../common/socket.h" #include "../common/timer.h" #include "../common/nullpo.h" +#include "../common/mmo.h" +#include "../common/db.h" +#include "../common/core.h" #include "log.h" #include "clif.h" @@ -16,6 +19,7 @@ #include "itemdb.h" #include "map.h" #include "pc.h" +#include "status.h" #include "skill.h" #include "mob.h" #include "pet.h" @@ -26,7 +30,6 @@ #include "script.h" #include "npc.h" #include "trade.h" -#include "core.h" #ifndef TXT_ONLY #include "mail.h" @@ -36,201 +39,233 @@ static char command_symbol = '@'; // first char of the commands (by [Yor]) -static char msg_table[1000][1024]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others) - -#define ATCOMMAND_FUNC(x) int atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message) -ATCOMMAND_FUNC(broadcast); -ATCOMMAND_FUNC(localbroadcast); -ATCOMMAND_FUNC(rurap); -ATCOMMAND_FUNC(rura); -ATCOMMAND_FUNC(where); -ATCOMMAND_FUNC(jumpto); -ATCOMMAND_FUNC(jump); -ATCOMMAND_FUNC(who); -ATCOMMAND_FUNC(who2); -ATCOMMAND_FUNC(who3); -ATCOMMAND_FUNC(whomap); -ATCOMMAND_FUNC(whomap2); -ATCOMMAND_FUNC(whomap3); -ATCOMMAND_FUNC(whogm); // by Yor -ATCOMMAND_FUNC(whozeny); // [Valaris] -ATCOMMAND_FUNC(happyhappyjoyjoy); // [Valaris] -ATCOMMAND_FUNC(save); -ATCOMMAND_FUNC(load); -ATCOMMAND_FUNC(speed); -ATCOMMAND_FUNC(storage); -ATCOMMAND_FUNC(guildstorage); -ATCOMMAND_FUNC(option); -ATCOMMAND_FUNC(hide); -ATCOMMAND_FUNC(jobchange); -ATCOMMAND_FUNC(die); -ATCOMMAND_FUNC(kill); -ATCOMMAND_FUNC(alive); -ATCOMMAND_FUNC(kami); -ATCOMMAND_FUNC(heal); -ATCOMMAND_FUNC(item); -ATCOMMAND_FUNC(item2); -ATCOMMAND_FUNC(itemreset); -ATCOMMAND_FUNC(itemcheck); -ATCOMMAND_FUNC(baselevelup); -ATCOMMAND_FUNC(joblevelup); -ATCOMMAND_FUNC(help); -ATCOMMAND_FUNC(gm); -ATCOMMAND_FUNC(pvpoff); -ATCOMMAND_FUNC(pvpon); -ATCOMMAND_FUNC(gvgoff); -ATCOMMAND_FUNC(gvgon); -ATCOMMAND_FUNC(model); -ATCOMMAND_FUNC(go); -ATCOMMAND_FUNC(monster); -ATCOMMAND_FUNC(monstersmall); -ATCOMMAND_FUNC(monsterbig); -ATCOMMAND_FUNC(spawn); -ATCOMMAND_FUNC(killmonster); -ATCOMMAND_FUNC(killmonster2); -ATCOMMAND_FUNC(refine); -ATCOMMAND_FUNC(produce); -ATCOMMAND_FUNC(memo); -ATCOMMAND_FUNC(gat); -ATCOMMAND_FUNC(packet); -ATCOMMAND_FUNC(statuspoint); -ATCOMMAND_FUNC(skillpoint); -ATCOMMAND_FUNC(zeny); -ATCOMMAND_FUNC(param); -ATCOMMAND_FUNC(guildlevelup); -ATCOMMAND_FUNC(makeegg); -ATCOMMAND_FUNC(hatch); -ATCOMMAND_FUNC(petfriendly); -ATCOMMAND_FUNC(pethungry); -ATCOMMAND_FUNC(petrename); -ATCOMMAND_FUNC(recall); -ATCOMMAND_FUNC(recallall); -ATCOMMAND_FUNC(revive); -ATCOMMAND_FUNC(character_stats_all); -ATCOMMAND_FUNC(character_save); -ATCOMMAND_FUNC(night); -ATCOMMAND_FUNC(day); -ATCOMMAND_FUNC(doom); -ATCOMMAND_FUNC(doommap); -ATCOMMAND_FUNC(raise); -ATCOMMAND_FUNC(raisemap); -ATCOMMAND_FUNC(character_baselevel); -ATCOMMAND_FUNC(character_joblevel); -ATCOMMAND_FUNC(kick); -ATCOMMAND_FUNC(kickall); -ATCOMMAND_FUNC(allskill); -ATCOMMAND_FUNC(questskill); -ATCOMMAND_FUNC(charquestskill); -ATCOMMAND_FUNC(lostskill); -ATCOMMAND_FUNC(charlostskill); -ATCOMMAND_FUNC(spiritball); -ATCOMMAND_FUNC(party); -ATCOMMAND_FUNC(guild); -ATCOMMAND_FUNC(charskreset); -ATCOMMAND_FUNC(charstreset); -ATCOMMAND_FUNC(charreset); -ATCOMMAND_FUNC(charstpoint); -ATCOMMAND_FUNC(charmodel); -ATCOMMAND_FUNC(charskpoint); -ATCOMMAND_FUNC(charzeny); -ATCOMMAND_FUNC(agitstart); -ATCOMMAND_FUNC(agitend); -ATCOMMAND_FUNC(reloaditemdb); -ATCOMMAND_FUNC(reloadmobdb); -ATCOMMAND_FUNC(reloadskilldb); -#ifndef TXT_ONLY -ATCOMMAND_FUNC(rehash);// by Fr3DBr -#else /* TXT_ONLY */ -ATCOMMAND_FUNC(reloadscript); -#endif /* TXT_ONLY */ -ATCOMMAND_FUNC(reloadgmdb); // by Yor -ATCOMMAND_FUNC(mapexit); -ATCOMMAND_FUNC(idsearch); -ATCOMMAND_FUNC(mapinfo); -ATCOMMAND_FUNC(dye); //** by fritz -ATCOMMAND_FUNC(hair_style); //** by fritz -ATCOMMAND_FUNC(hair_color); //** by fritz -ATCOMMAND_FUNC(stat_all); //** by fritz -ATCOMMAND_FUNC(char_change_sex); // by Yor -ATCOMMAND_FUNC(char_block); // by Yor -ATCOMMAND_FUNC(char_ban); // by Yor -ATCOMMAND_FUNC(char_unblock); // by Yor -ATCOMMAND_FUNC(char_unban); // by Yor -ATCOMMAND_FUNC(mount_peco); // by Valaris -ATCOMMAND_FUNC(char_mount_peco); // by Yor -ATCOMMAND_FUNC(guildspy); // [Syrus22] -ATCOMMAND_FUNC(partyspy); // [Syrus22] -ATCOMMAND_FUNC(repairall); // [Valaris] -ATCOMMAND_FUNC(guildrecall); // by Yor -ATCOMMAND_FUNC(partyrecall); // by Yor -//ATCOMMAND_FUNC(nuke); // [Valaris] -ATCOMMAND_FUNC(enablenpc); -ATCOMMAND_FUNC(disablenpc); -ATCOMMAND_FUNC(servertime); // by Yor -ATCOMMAND_FUNC(chardelitem); // by Yor -ATCOMMAND_FUNC(jail); // by Yor -ATCOMMAND_FUNC(unjail); // by Yor -ATCOMMAND_FUNC(disguise); // [Valaris] -ATCOMMAND_FUNC(undisguise); // by Yor -ATCOMMAND_FUNC(chardisguise); // Kalaspuff -ATCOMMAND_FUNC(charundisguise); // Kalaspuff -ATCOMMAND_FUNC(email); // by Yor -ATCOMMAND_FUNC(effect);//by Apple -ATCOMMAND_FUNC(character_item_list); // by Yor -ATCOMMAND_FUNC(character_storage_list); // by Yor -ATCOMMAND_FUNC(character_cart_list); // by Yor -ATCOMMAND_FUNC(addwarp); // by MouseJstr -ATCOMMAND_FUNC(follow); // by MouseJstr -ATCOMMAND_FUNC(skillon); // by MouseJstr -ATCOMMAND_FUNC(skilloff); // by MouseJstr -ATCOMMAND_FUNC(killer); // by MouseJstr -ATCOMMAND_FUNC(npcmove); // by MouseJstr -ATCOMMAND_FUNC(killable); // by MouseJstr -ATCOMMAND_FUNC(charkillable); // by MouseJstr -ATCOMMAND_FUNC(chareffect); // by MouseJstr -ATCOMMAND_FUNC(chardye); // by MouseJstr -ATCOMMAND_FUNC(charhairstyle); // by MouseJstr -ATCOMMAND_FUNC(charhaircolor); // by MouseJstr -ATCOMMAND_FUNC(dropall); // by MouseJstr -ATCOMMAND_FUNC(chardropall); // by MouseJstr -ATCOMMAND_FUNC(storeall); // by MouseJstr -ATCOMMAND_FUNC(charstoreall); // by MouseJstr -ATCOMMAND_FUNC(skillid); // by MouseJstr -ATCOMMAND_FUNC(useskill); // by MouseJstr -ATCOMMAND_FUNC(summon); -ATCOMMAND_FUNC(rain); -ATCOMMAND_FUNC(snow); -ATCOMMAND_FUNC(sakura); -ATCOMMAND_FUNC(fog); -ATCOMMAND_FUNC(leaves); -ATCOMMAND_FUNC(adjgmlvl); // by MouseJstr -ATCOMMAND_FUNC(adjcmdlvl); // by MouseJstr -ATCOMMAND_FUNC(trade); // by MouseJstr -ATCOMMAND_FUNC(send); // by davidsiaw -ATCOMMAND_FUNC(setbattleflag); // by MouseJstr -ATCOMMAND_FUNC(unmute); // [Valaris] -ATCOMMAND_FUNC(uptime); // by MC Cameri -ATCOMMAND_FUNC(changesex); // by MC Cameri -ATCOMMAND_FUNC(mute); // celest -ATCOMMAND_FUNC(refresh); // by MC Cameri -ATCOMMAND_FUNC(petid); // by MC Cameri -ATCOMMAND_FUNC(identify); // by MC Cameri -ATCOMMAND_FUNC(gmotd); // Added by MC Cameri, created by davidsiaw -ATCOMMAND_FUNC(misceffect); // by MC Cameri +#define MAX_MSG 1000 +char *msg_table[MAX_MSG]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others) + +#define ACMD_FUNC(x) int atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message) +ACMD_FUNC(broadcast); +ACMD_FUNC(localbroadcast); +ACMD_FUNC(rura); +ACMD_FUNC(where); +ACMD_FUNC(jumpto); +ACMD_FUNC(jump); +ACMD_FUNC(who); +ACMD_FUNC(who2); +ACMD_FUNC(who3); +ACMD_FUNC(whomap); +ACMD_FUNC(whomap2); +ACMD_FUNC(whomap3); +ACMD_FUNC(whogm); // by Yor +ACMD_FUNC(whozeny); // [Valaris] +ACMD_FUNC(happyhappyjoyjoy); // [Valaris] +ACMD_FUNC(save); +ACMD_FUNC(load); +ACMD_FUNC(speed); +ACMD_FUNC(storage); +ACMD_FUNC(guildstorage); +ACMD_FUNC(option); +ACMD_FUNC(hide); +ACMD_FUNC(jobchange); +ACMD_FUNC(die); +ACMD_FUNC(kill); +ACMD_FUNC(alive); +ACMD_FUNC(kami); +ACMD_FUNC(heal); +ACMD_FUNC(item); +ACMD_FUNC(item2); +ACMD_FUNC(itemreset); +ACMD_FUNC(itemcheck); +ACMD_FUNC(baselevelup); +ACMD_FUNC(joblevelup); +ACMD_FUNC(help); +ACMD_FUNC(gm); +ACMD_FUNC(pvpoff); +ACMD_FUNC(pvpon); +ACMD_FUNC(gvgoff); +ACMD_FUNC(gvgon); +ACMD_FUNC(model); +ACMD_FUNC(go); +ACMD_FUNC(monster); +ACMD_FUNC(monstersmall); +ACMD_FUNC(monsterbig); +ACMD_FUNC(spawn); +ACMD_FUNC(killmonster); +ACMD_FUNC(killmonster2); +ACMD_FUNC(refine); +ACMD_FUNC(produce); +ACMD_FUNC(memo); +ACMD_FUNC(gat); +ACMD_FUNC(packet); +ACMD_FUNC(statuspoint); +ACMD_FUNC(skillpoint); +ACMD_FUNC(zeny); +ACMD_FUNC(param); +ACMD_FUNC(guildlevelup); +ACMD_FUNC(makeegg); +ACMD_FUNC(hatch); +ACMD_FUNC(petfriendly); +ACMD_FUNC(pethungry); +ACMD_FUNC(petrename); +ACMD_FUNC(recall); +ACMD_FUNC(recallall); +ACMD_FUNC(revive); +ACMD_FUNC(character_stats_all); +ACMD_FUNC(character_save); +ACMD_FUNC(night); +ACMD_FUNC(day); +ACMD_FUNC(doom); +ACMD_FUNC(doommap); +ACMD_FUNC(raise); +ACMD_FUNC(raisemap); +ACMD_FUNC(character_baselevel); +ACMD_FUNC(character_joblevel); +ACMD_FUNC(kick); +ACMD_FUNC(kickall); +ACMD_FUNC(allskill); +ACMD_FUNC(questskill); +ACMD_FUNC(charquestskill); +ACMD_FUNC(lostskill); +ACMD_FUNC(charlostskill); +ACMD_FUNC(spiritball); +ACMD_FUNC(party); +ACMD_FUNC(guild); +ACMD_FUNC(charskreset); +ACMD_FUNC(charstreset); +ACMD_FUNC(charreset); +ACMD_FUNC(charstpoint); +ACMD_FUNC(charmodel); +ACMD_FUNC(charskpoint); +ACMD_FUNC(agitstart); +ACMD_FUNC(agitend); +ACMD_FUNC(reloaditemdb); +ACMD_FUNC(reloadmobdb); +ACMD_FUNC(reloadskilldb); +ACMD_FUNC(reloadscript); +ACMD_FUNC(reloadgmdb); // by Yor +ACMD_FUNC(reloadatcommand); +ACMD_FUNC(reloadbattleconf); +ACMD_FUNC(reloadstatusdb); +ACMD_FUNC(reloadpcdb); +ACMD_FUNC(mapexit); +ACMD_FUNC(idsearch); +ACMD_FUNC(mapinfo); +ACMD_FUNC(dye); //** by fritz +ACMD_FUNC(hair_style); //** by fritz +ACMD_FUNC(hair_color); //** by fritz +ACMD_FUNC(stat_all); //** by fritz +ACMD_FUNC(char_change_sex); // by Yor +ACMD_FUNC(char_block); // by Yor +ACMD_FUNC(char_ban); // by Yor +ACMD_FUNC(char_unblock); // by Yor +ACMD_FUNC(char_unban); // by Yor +ACMD_FUNC(mount_peco); // by Valaris +ACMD_FUNC(char_mount_peco); // by Yor +ACMD_FUNC(guildspy); // [Syrus22] +ACMD_FUNC(partyspy); // [Syrus22] +ACMD_FUNC(repairall); // [Valaris] +ACMD_FUNC(guildrecall); // by Yor +ACMD_FUNC(partyrecall); // by Yor +ACMD_FUNC(nuke); // [Valaris] +ACMD_FUNC(enablenpc); +ACMD_FUNC(hidenpc); +ACMD_FUNC(disablenpc); +ACMD_FUNC(servertime); // by Yor +ACMD_FUNC(chardelitem); // by Yor +ACMD_FUNC(jail); // by Yor +ACMD_FUNC(unjail); // by Yor +ACMD_FUNC(disguise); // [Valaris] +ACMD_FUNC(undisguise); // by Yor +ACMD_FUNC(chardisguise); // Kalaspuff +ACMD_FUNC(charundisguise); // Kalaspuff +ACMD_FUNC(email); // by Yor +ACMD_FUNC(effect);//by Apple +ACMD_FUNC(character_cart_list); // by Yor +ACMD_FUNC(addwarp); // by MouseJstr +ACMD_FUNC(follow); // by MouseJstr +ACMD_FUNC(skillon); // by MouseJstr +ACMD_FUNC(skilloff); // by MouseJstr +ACMD_FUNC(killer); // by MouseJstr +ACMD_FUNC(npcmove); // by MouseJstr +ACMD_FUNC(killable); // by MouseJstr +ACMD_FUNC(charkillable); // by MouseJstr +ACMD_FUNC(dropall); // by MouseJstr +ACMD_FUNC(chardropall); // by MouseJstr +ACMD_FUNC(storeall); // by MouseJstr +ACMD_FUNC(charstoreall); // by MouseJstr +ACMD_FUNC(skillid); // by MouseJstr +ACMD_FUNC(useskill); // by MouseJstr +ACMD_FUNC(summon); +ACMD_FUNC(rain); +ACMD_FUNC(snow); +ACMD_FUNC(sakura); +ACMD_FUNC(fog); +ACMD_FUNC(leaves); +ACMD_FUNC(adjgmlvl); // by MouseJstr +ACMD_FUNC(adjcmdlvl); // by MouseJstr +ACMD_FUNC(trade); // by MouseJstr +ACMD_FUNC(send); // by davidsiaw +ACMD_FUNC(setbattleflag); // by MouseJstr +ACMD_FUNC(unmute); // [Valaris] +ACMD_FUNC(clearweather); // Dexity +ACMD_FUNC(uptime); // by MC Cameri +ACMD_FUNC(changesex); // by MC Cameri +ACMD_FUNC(mute); // celest +ACMD_FUNC(refresh); // by MC Cameri +ACMD_FUNC(petid); // by MC Cameri +ACMD_FUNC(identify); // by MC Cameri +ACMD_FUNC(gmotd); // Added by MC Cameri, created by davidsiaw +ACMD_FUNC(misceffect); // by MC Cameri +ACMD_FUNC(mobsearch); +ACMD_FUNC(cleanmap); +ACMD_FUNC(npctalk); +ACMD_FUNC(pettalk); +ACMD_FUNC(users); +ACMD_FUNC(autoloot); // by Upa-Kun #ifndef TXT_ONLY -ATCOMMAND_FUNC(checkmail); // [Valaris] -ATCOMMAND_FUNC(listmail); // [Valaris] -ATCOMMAND_FUNC(listnewmail); // [Valaris] -ATCOMMAND_FUNC(readmail); // [Valaris] -ATCOMMAND_FUNC(sendmail); // [Valaris] -ATCOMMAND_FUNC(sendprioritymail); // [Valaris] -ATCOMMAND_FUNC(deletemail); // [Valaris] -ATCOMMAND_FUNC(sound); // [Valaris] -ATCOMMAND_FUNC(refreshonline); // [Valaris] +ACMD_FUNC(checkmail); // [Valaris] +ACMD_FUNC(listmail); // [Valaris] +ACMD_FUNC(listnewmail); // [Valaris] +ACMD_FUNC(readmail); // [Valaris] +ACMD_FUNC(sendmail); // [Valaris] +ACMD_FUNC(sendprioritymail); // [Valaris] +ACMD_FUNC(deletemail); // [Valaris] +//ACMD_FUNC(sound); // [Valaris] +ACMD_FUNC(refreshonline); // [Valaris] #endif /* TXT_ONLY */ -ATCOMMAND_FUNC(skilltree); // by MouseJstr +ACMD_FUNC(skilltree); // by MouseJstr + +ACMD_FUNC(marry); // by MouseJstr +ACMD_FUNC(divorce); // by MouseJstr +ACMD_FUNC(rings); // by MouseJstr + +ACMD_FUNC(grind); // by MouseJstr +ACMD_FUNC(grind2); // by MouseJstr + +#ifdef DMALLOC +ACMD_FUNC(dmstart); // by MouseJstr +ACMD_FUNC(dmtick); // by MouseJstr +#endif + +ACMD_FUNC(jumptoid); // by Dino9021 +ACMD_FUNC(jumptoid2); // by Dino9021 +ACMD_FUNC(recallid); // by Dino9021 +ACMD_FUNC(recallid2); // by Dino9021 +ACMD_FUNC(kickid); // by Dino9021 +ACMD_FUNC(kickid2); // by Dino9021 +ACMD_FUNC(reviveid); // by Dino9021 +ACMD_FUNC(reviveid2); // by Dino9021 +ACMD_FUNC(killid); // by Dino9021 +ACMD_FUNC(killid2); // by Dino9021 +ACMD_FUNC(charkillableid); // by Dino9021 +ACMD_FUNC(charkillableid2); // by Dino9021 +ACMD_FUNC(sound); +ACMD_FUNC(undisguiseall); +ACMD_FUNC(disguiseall); +ACMD_FUNC(changelook); +ACMD_FUNC(mobinfo); //by Lupus +ACMD_FUNC(adopt); // by Veider /*========================================== *AtCommandInfo atcommand_info[]\‘¢‘̂̒è‹` @@ -240,8 +275,6 @@ ATCOMMAND_FUNC(skilltree); // by MouseJstr // First char of commands is configured in atcommand_athena.conf. Leave @ in this list for default value. // to set default level, read atcommand_athena.conf first please. static AtCommandInfo atcommand_info[] = { - { AtCommand_RuraP, "@rura+", 60, atcommand_rurap }, - { AtCommand_RuraP, "@charwarp", 60, atcommand_rurap }, { AtCommand_Rura, "@rura", 40, atcommand_rura }, { AtCommand_Warp, "@warp", 40, atcommand_rura }, { AtCommand_Where, "@where", 1, atcommand_where }, @@ -359,16 +392,15 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_ReloadItemDB, "@reloaditemdb", 99, atcommand_reloaditemdb }, // admin command { AtCommand_ReloadMobDB, "@reloadmobdb", 99, atcommand_reloadmobdb }, // admin command { AtCommand_ReloadSkillDB, "@reloadskilldb", 99, atcommand_reloadskilldb }, // admin command -#ifndef TXT_ONLY - { AtCommand_Rehash, "@rehash", 99, atcommand_rehash }, // admin command -#else /* TXT_ONLY */ { AtCommand_ReloadScript, "@reloadscript", 99, atcommand_reloadscript }, // admin command -#endif /* TXT_ONLY */ { AtCommand_ReloadGMDB, "@reloadgmdb", 99, atcommand_reloadgmdb }, // admin command + { AtCommand_ReloadAtcommand, "@reloadatcommand", 99, atcommand_reloadatcommand }, + { AtCommand_ReloadBattleConf, "@reloadbattleconf",99, atcommand_reloadbattleconf }, + { AtCommand_ReloadStatusDB, "@reloadstatusdb", 99, atcommand_reloadstatusdb }, + { AtCommand_ReloadPcDB, "@reloadpcdb", 99, atcommand_reloadpcdb }, { AtCommand_CharModel, "@charmodel", 50, atcommand_charmodel }, { AtCommand_CharSKPoint, "@charskpoint", 60, atcommand_charskpoint }, { AtCommand_CharSTPoint, "@charstpoint", 60, atcommand_charstpoint }, - { AtCommand_CharZeny, "@charzeny", 60, atcommand_charzeny }, { AtCommand_MapInfo, "@mapinfo", 99, atcommand_mapinfo }, { AtCommand_Dye, "@dye", 40, atcommand_dye }, // by fritz { AtCommand_Dye, "@ccolor", 40, atcommand_dye }, // by fritz @@ -380,7 +412,7 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_StatAll, "@statsall", 60, atcommand_stat_all }, { AtCommand_StatAll, "@allstats", 60, atcommand_stat_all }, // by fritz { AtCommand_StatAll, "@allstat", 60, atcommand_stat_all }, // by fritz - { AtCommand_CharChangeSex, "@charchangesex", 60, atcommand_char_change_sex }, // by Yor +// { AtCommand_CharChangeSex, "@charchangesex", 60, atcommand_char_change_sex }, // by Yor { AtCommand_CharBlock, "@block", 60, atcommand_char_block }, // by Yor { AtCommand_CharBlock, "@charblock", 60, atcommand_char_block }, // by Yor { AtCommand_CharBan, "@ban", 60, atcommand_char_ban }, // by Yor @@ -400,8 +432,9 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_RepairAll, "@repairall", 60, atcommand_repairall }, // [Valaris] { AtCommand_GuildRecall, "@guildrecall", 60, atcommand_guildrecall }, // by Yor { AtCommand_PartyRecall, "@partyrecall", 60, atcommand_partyrecall }, // by Yor -// { AtCommand_Nuke, "@nuke", 60, atcommand_nuke }, // [Valaris] + { AtCommand_Nuke, "@nuke", 60, atcommand_nuke }, // [Valaris] { AtCommand_Enablenpc, "@enablenpc", 80, atcommand_enablenpc }, // [] + { AtCommand_Hidenpc, "@hidenpc", 80, atcommand_hidenpc }, // [] { AtCommand_Disablenpc, "@disablenpc", 80, atcommand_disablenpc }, // [] { AtCommand_ServerTime, "@time", 0, atcommand_servertime }, // by Yor { AtCommand_ServerTime, "@date", 0, atcommand_servertime }, // by Yor @@ -419,8 +452,8 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_CharUnDisguise, "@charundisguise", 60, atcommand_charundisguise }, // Kalaspuff { AtCommand_EMail, "@email", 0, atcommand_email }, // by Yor { AtCommand_Effect, "@effect", 40, atcommand_effect }, // by Apple - { AtCommand_Char_Item_List, "@charitemlist", 40, atcommand_character_item_list }, // by Yor - { AtCommand_Char_Storage_List, "@charstoragelist", 40, atcommand_character_storage_list }, // by Yor +// { AtCommand_Char_Item_List, "@charitemlist", 40, atcommand_character_item_list }, // by Yor, now #itemlist +// { AtCommand_Char_Storage_List, "@charstoragelist", 40, atcommand_character_storage_list }, // by Yor, now #storagelist { AtCommand_Char_Cart_List, "@charcartlist", 40, atcommand_character_cart_list }, // by Yor { AtCommand_Follow, "@follow", 10, atcommand_follow }, // by MouseJstr { AtCommand_AddWarp, "@addwarp", 20, atcommand_addwarp }, // by MouseJstr @@ -430,12 +463,6 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_NpcMove, "@npcmove", 20, atcommand_npcmove }, // by MouseJstr { AtCommand_Killable, "@killable", 40, atcommand_killable }, // by MouseJstr { AtCommand_CharKillable, "@charkillable", 40, atcommand_charkillable }, // by MouseJstr - { AtCommand_Chareffect, "@chareffect", 40, atcommand_chareffect }, // MouseJstr -/* - { AtCommand_Chardye, "@chardye", 40, atcommand_chardye }, // MouseJstr - { AtCommand_Charhairstyle, "@charhairstyle", 40, atcommand_charhairstyle }, // MouseJstr - { AtCommand_Charhaircolor, "@charhaircolor", 40, atcommand_charhaircolor }, // MouseJstr -*/ { AtCommand_Dropall, "@dropall", 40, atcommand_dropall }, // MouseJstr { AtCommand_Chardropall, "@chardropall", 40, atcommand_chardropall }, // MouseJstr { AtCommand_Storeall, "@storeall", 40, atcommand_storeall }, // MouseJstr @@ -459,8 +486,9 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_Send, "@send", 60, atcommand_send }, { AtCommand_SetBattleFlag, "@setbattleflag", 60, atcommand_setbattleflag }, { AtCommand_UnMute, "@unmute", 60, atcommand_unmute }, // [Valaris] + { AtCommand_Clearweather, "@clearweather", 99, atcommand_clearweather }, // Dexity { AtCommand_UpTime, "@uptime", 0, atcommand_uptime }, // by MC Cameri - { AtCommand_ChangeSex, "@changesex", 1, atcommand_changesex }, // by MC Cameri +// { AtCommand_ChangeSex, "@changesex", 1, atcommand_changesex }, // by MC Cameri { AtCommand_Mute, "@mute", 99, atcommand_mute }, // [celest] { AtCommand_Mute, "@red", 99, atcommand_mute }, // [celest] { AtCommand_WhoZeny, "@whozeny", 20, atcommand_whozeny }, // [Valaris] @@ -470,6 +498,12 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_Identify, "@identify", 40, atcommand_identify }, // by MC Cameri { AtCommand_Gmotd, "@gmotd", 0, atcommand_gmotd }, // Added by MC Cameri, created by davidsiaw { AtCommand_MiscEffect, "@misceffect", 50, atcommand_misceffect }, // by MC Cameri + { AtCommand_MobSearch, "@mobsearch", 0, atcommand_mobsearch }, + { AtCommand_CleanMap, "@cleanmap", 0, atcommand_cleanmap }, + { AtCommand_NpcTalk, "@npctalk", 0, atcommand_npctalk }, + { AtCommand_PetTalk, "@pettalk", 0, atcommand_pettalk }, + { AtCommand_Users, "@users", 0, atcommand_users }, + { AtCommand_ResetState, "/reset", 40, NULL }, #ifndef TXT_ONLY // sql-only commands { AtCommand_CheckMail, "@checkmail", 1, atcommand_listmail }, // [Valaris] @@ -483,17 +517,60 @@ static AtCommandInfo atcommand_info[] = { #endif /* TXT_ONLY */ { AtCommand_SkillTree, "@skilltree", 40, atcommand_skilltree }, // [MouseJstr] + { AtCommand_Marry, "@marry", 40, atcommand_marry }, // [MouseJstr] + { AtCommand_Divorce, "@divorce", 40, atcommand_divorce }, // [MouseJstr] + { AtCommand_Rings, "@rings", 40, atcommand_rings }, // [MouseJstr] + { AtCommand_Grind, "@grind", 99, atcommand_grind }, // [MouseJstr] + { AtCommand_Grind2, "@grind2", 99, atcommand_grind2 }, // [MouseJstr] + +#ifdef DMALLOC + { AtCommand_DMStart, "@dmstart", 99, atcommand_dmstart }, // [MouseJstr] + { AtCommand_DMTick, "@dmtick", 99, atcommand_dmtick }, // [MouseJstr] +#endif + { AtCommand_JumpToId, "@jumptoid", 20, atcommand_jumptoid }, // [Dino9021] + { AtCommand_JumpToId, "@warptoid", 20, atcommand_jumptoid }, // [Dino9021] + { AtCommand_JumpToId, "@gotoid", 20, atcommand_jumptoid }, // [Dino9021] + { AtCommand_JumpToId2, "@jumptoid2", 20, atcommand_jumptoid2 }, // [Dino9021] + { AtCommand_JumpToId2, "@warptoid2", 20, atcommand_jumptoid2 }, // [Dino9021] + { AtCommand_JumpToId2, "@gotoid2", 20, atcommand_jumptoid2 }, // [Dino9021] + { AtCommand_RecallId, "@recallid", 60, atcommand_recallid }, // [Dino9021] + { AtCommand_RecallId2, "@recallid2", 60, atcommand_recallid2 }, // [Dino9021] + { AtCommand_KickId, "@kickid", 99, atcommand_kickid }, // [Dino9021] + { AtCommand_KickId2, "@kickid2", 99, atcommand_kickid2 }, // [Dino9021] + { AtCommand_ReviveId, "@reviveid", 60, atcommand_reviveid }, // [Dino9021] + { AtCommand_ReviveId2, "@reviveid2", 60, atcommand_reviveid2 }, // [Dino9021] + { AtCommand_KillId, "@killid", 60, atcommand_killid }, // [Dino9021] + { AtCommand_KillId2, "@killid2", 60, atcommand_killid2 }, // [Dino9021] + { AtCommand_CharKillableId, "@charkillableid", 40, atcommand_charkillableid }, // [Dino9021] + { AtCommand_CharKillableId2, "@charkillableid2", 40, atcommand_charkillableid2 }, // [Dino9021] + { AtCommand_Sound, "@sound", 40, atcommand_sound }, + { AtCommand_UndisguiseAll, "@undisguiseall", 99, atcommand_undisguiseall }, + { AtCommand_DisguiseAll, "@disguiseall", 99, atcommand_disguiseall }, + { AtCommand_ChangeLook, "@changelook", 99, atcommand_changelook }, + { AtCommand_AutoLoot, "@autoloot", 10, atcommand_autoloot }, // Upa-Kun + { AtCommand_MobInfo, "@mobinfo", 1, atcommand_mobinfo }, // [Lupus] + { AtCommand_MobInfo, "@monsterinfo", 1, atcommand_mobinfo }, // [Lupus] + { AtCommand_MobInfo, "@mi", 1, atcommand_mobinfo }, // [Lupus] + { AtCommand_Adopt, "@adopt", 40, atcommand_adopt }, // [Veider] + // add new commands before this line { AtCommand_Unknown, NULL, 1, NULL } }; +/*========================================= + * Generic variables + *----------------------------------------- + */ +char atcmd_output[200]; +char atcmd_player_name[100]; + /*==================================================== * This function return the name of the job (by [Yor]) *---------------------------------------------------- */ -char * job_name(int class) { - switch (class) { +char * job_name(int class_) { + switch (class_) { case 0: return "Novice"; case 1: return "Swordsman"; case 2: return "Mage"; @@ -597,7 +674,7 @@ int lowtohigh_compare (const void * a, const void * b) // Return the message string of the specified number by [Yor] //----------------------------------------------------------- char * msg_txt(int msg_number) { - if (msg_number >= 0 && msg_number < (int)(sizeof(msg_table) / sizeof(msg_table[0])) && + if (msg_number >= 0 && msg_number < MAX_MSG && msg_table[msg_number] != NULL && msg_table[msg_number][0] != '\0') return msg_table[msg_number]; @@ -607,9 +684,9 @@ char * msg_txt(int msg_number) { //------------------------------------------------------------ // E-mail check: return 0 (not correct) or 1 (valid). by [Yor] //------------------------------------------------------------ -int e_mail_check(unsigned char *email) { +int e_mail_check(char *email) { char ch; - unsigned char* last_arobas; + char* last_arobas; // athena limits if (strlen(email) < 3 || strlen(email) > 39) @@ -670,6 +747,11 @@ is_atcommand(const int fd, struct map_session_data* sd, const char* message, int nullpo_retr(AtCommand_None, sd); + if (!battle_config.allow_atcommand_when_mute && + sd->sc_count && sd->sc_data[SC_NOCHAT].timer != -1) { + return AtCommand_Unknown; + } + if (!message || !*message) return AtCommand_None; @@ -683,13 +765,12 @@ is_atcommand(const int fd, struct map_session_data* sd, const char* message, int if (!*str) return AtCommand_None; - type = atcommand(gmlvl > 0 ? gmlvl : pc_isGM(sd), str, &info); + type = atcommand(sd, gmlvl > 0 ? gmlvl : pc_isGM(sd), str, &info); if (type != AtCommand_None) { char command[100]; - char output[200]; const char* p = str; memset(command, '\0', sizeof(command)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); while (*p && !isspace(*p)) p++; if (p - str >= sizeof(command)) // too long @@ -699,20 +780,16 @@ is_atcommand(const int fd, struct map_session_data* sd, const char* message, int p++; if (type == AtCommand_Unknown || info.proc == NULL) { - sprintf(output, msg_table[153], command); // %s is Unknown Command. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[153], command); // %s is Unknown Command. + clif_displaymessage(fd, atcmd_output); } else { if (info.proc(fd, sd, command, p) != 0) { // Command can not be executed - sprintf(output, msg_table[154], command); // %s failed. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[154], command); // %s failed. + clif_displaymessage(fd, atcmd_output); } } - // ToDo: Fix Logs :) - //if((log_config.gm) && (info.level >= log_config.gm)) - // log_atcommand(sd, message); - return info.type; } @@ -723,7 +800,7 @@ is_atcommand(const int fd, struct map_session_data* sd, const char* message, int * *------------------------------------------ */ -AtCommandType atcommand(const int level, const char* message, struct AtCommandInfo* info) { +AtCommandType atcommand(struct map_session_data* sd, const int level, const char* message, struct AtCommandInfo* info) { char* p = (char *)message; // it's 'char' and not 'const char' to have possibility to modify the first character if necessary if (!info) @@ -756,6 +833,8 @@ AtCommandType atcommand(const int level, const char* message, struct AtCommandIn return AtCommand_None; else return AtCommand_Unknown; + } else if((log_config.gm) && (atcommand_info[i].level >= log_config.gm)) { + log_atcommand(sd, message); } memcpy(info, &atcommand_info[i], sizeof atcommand_info[i]); } else { @@ -770,49 +849,73 @@ AtCommandType atcommand(const int level, const char* message, struct AtCommandIn *------------------------------------------ */ static int atkillmonster_sub(struct block_list *bl, va_list ap) { - int flag = va_arg(ap, int); - - nullpo_retr(0, bl); + struct mob_data *md; + int flag; + + nullpo_retr(0, ap); + nullpo_retr(0, md=(struct mob_data *)bl); + flag = va_arg(ap, int); if (flag) - mob_damage(NULL, (struct mob_data *)bl, ((struct mob_data *)bl)->hp, 2); + mob_damage(NULL, md, md->hp, 2); else - mob_delete((struct mob_data *)bl); - + mob_delete(md); + return 0; } - -#ifndef TXT_ONLY -static int atkillnpc_sub(struct block_list *bl, va_list ap) +/*========================================== + * Mob search + *------------------------------------------ + */ +static int atmobsearch_sub(struct block_list *bl,va_list ap) { - int flag = va_arg(ap,int); + int mob_id,fd; + static int number=0; + struct mob_data *md; - nullpo_retr(0, bl); + nullpo_retr(0, bl); - npc_delete((struct npc_data *)bl); + if(!ap){ + number=0; + return 0; + } + mob_id = va_arg(ap,int); + fd = va_arg(ap,int); - flag = 0; + md = (struct mob_data *)bl; - return 0; + if(md && fd && (mob_id==-1 || (md->class_==mob_id))){ + snprintf(atcmd_output, sizeof atcmd_output, "%2d[%3d:%3d] %s", + ++number,bl->x, bl->y,md->name); + clif_displaymessage(fd, atcmd_output); + } + return 0; } - -void rehash( const int fd, struct map_session_data* sd ) +/*========================================== + * cleanmap + *------------------------------------------ + */ +static int atcommand_cleanmap_sub(struct block_list *bl,va_list ap) { - int map_id = 0; + struct flooritem_data *fitem; - int LOADED_MAPS = map_num; - - for (map_id = 0; map_id < LOADED_MAPS;map_id++) { + nullpo_retr(0, bl); - if (map_id > LOADED_MAPS) - break; + fitem = (struct flooritem_data *)bl; + if(fitem==NULL || fitem->bl.type!=BL_ITEM){ + if(battle_config.error_log) + printf("map_clearflooritem_timer : error\n"); + return 1; + } + delete_timer(fitem->cleartimer,map_clearflooritem_timer); + if(fitem->item_data.card[0] == (short)0xff00) + intif_delete_petdata(*((long *)(&fitem->item_data.card[1]))); + clif_clearflooritem(fitem,0); + map_delobject(fitem->bl.id); - map_foreachinarea(atkillmonster_sub, map_id, 0, 0, map[map_id].xs, map[map_id].ys, BL_MOB, 0); - map_foreachinarea(atkillnpc_sub, map_id, 0, 0, map[map_id].xs, map[map_id].ys, BL_NPC, 0); - } + return 0; } -#endif /* not TXT_ONLY */ /*========================================== * Read Message Data *------------------------------------------ @@ -821,12 +924,15 @@ int msg_config_read(const char *cfgName) { int msg_number; char line[1024], w1[1024], w2[1024]; FILE *fp; + static int called = 1; if ((fp = fopen(cfgName, "r")) == NULL) { printf("Messages file not found: %s\n", cfgName); return 1; } + if ((--called) == 0) + memset(&msg_table[0], 0, sizeof(msg_table[0]) * MAX_MSG); while(fgets(line, sizeof(line)-1, fp)) { if (line[0] == '/' && line[1] == '/') continue; @@ -835,9 +941,13 @@ int msg_config_read(const char *cfgName) { msg_config_read(w2); } else { msg_number = atoi(w1); - if (msg_number >= 0 && msg_number < (int)(sizeof(msg_table) / sizeof(msg_table[0]))) - strcpy(msg_table[msg_number], w2); + if (msg_number >= 0 && msg_number < MAX_MSG) { + if (msg_table[msg_number] != NULL) + aFree(msg_table[msg_number]); + msg_table[msg_number] = (char *)aCalloc(strlen(w2) + 1, sizeof (char)); + strcpy(msg_table[msg_number],w2); // printf("message #%d: '%s'.\n", msg_number, msg_table[msg_number]); + } } } } @@ -847,6 +957,17 @@ int msg_config_read(const char *cfgName) { } /*========================================== + * Cleanup Message Data + *------------------------------------------ + */ +void do_final_msg () { + int i; + for (i = 0; i < MAX_MSG; i++) + aFree(msg_table[i]); + return; +} + +/*========================================== * *------------------------------------------ */ @@ -932,73 +1053,7 @@ int atcommand_send( case 4: WBUFW(buf,0)=0x190; } - - - } - return 0; -} - -/*========================================== - * @rura+ - *------------------------------------------ - */ -int atcommand_rurap( - const int fd, struct map_session_data* sd, - const char* command, const char* message) -{ - char map_name[100]; - char character[100]; - int x = 0, y = 0; - struct map_session_data *pl_sd; - int m; - - memset(map_name, '\0', sizeof(map_name)); - memset(character, '\0', sizeof(character)); - - if (!message || !*message || sscanf(message, "%99s %d %d %99[^\n]", map_name, &x, &y, character) < 4) { - clif_displaymessage(fd, "Usage: @charwarp/@rura+ <mapname> <x> <y> <char name>"); - return -1; - } - - if (x <= 0) - x = rand() % 399 + 1; - if (y <= 0) - y = rand() % 399 + 1; - if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat) - strcat(map_name, ".gat"); - - if ((pl_sd = map_nick2sd(character)) != NULL) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can rura+ only lower or same GM level - if (x > 0 && x < 400 && y > 0 && y < 400) { - m = map_mapname2mapid(map_name); - if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp someone to this map."); - return -1; - } - if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp this player from its actual map."); - return -1; - } - if (pc_setpos(pl_sd, map_name, x, y, 3) == 0) { - clif_displaymessage(pl_sd->fd, msg_table[0]); // Warped. - clif_displaymessage(fd, msg_table[15]); // Player warped (message sends to player too). - } else { - clif_displaymessage(fd, msg_table[1]); // Map not found. - return -1; - } - } else { - clif_displaymessage(fd, msg_table[2]); // Coordinates out of range. - return -1; - } - } else { - clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. - return -1; - } - } else { - clif_displaymessage(fd, msg_table[3]); // Character not found. - return -1; } - return 0; } @@ -1015,6 +1070,8 @@ int atcommand_rura( int x = 0, y = 0; int m; + nullpo_retr(-1, sd); + memset(map_name, '\0', sizeof(map_name)); if (!message || !*message || sscanf(message, "%99s %d %d", map_name, &x, &y) < 1) { @@ -1033,11 +1090,11 @@ int atcommand_rura( if (x > 0 && x < 400 && y > 0 && y < 400) { m = map_mapname2mapid(map_name); if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp you to this map."); + clif_displaymessage(fd, msg_table[247]); return -1; } if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp you from your actual map."); + clif_displaymessage(fd, msg_table[248]); return -1; } if (pc_setpos(sd, map_name, x, y, 3) == 0) @@ -1062,30 +1119,28 @@ int atcommand_where( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; - char output[200]; struct map_session_data *pl_sd = NULL; nullpo_retr(-1, sd); if (!message || !*message) return -1; - memset(character, '\0', sizeof character); - if (sscanf(message, "%99[^\n]", character) < 1) + memset(atcmd_player_name, '\0', sizeof atcmd_player_name); + if (sscanf(message, "%99[^\n]", atcmd_player_name) < 1) return -1; - if(strncmp(sd->status.name,character,24)==0) + if(strncmp(sd->status.name,atcmd_player_name,24)==0) return -1; - if ((pl_sd = map_nick2sd(character)) == NULL) { - snprintf(output, sizeof output, "%s %d %d", + if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) { + snprintf(atcmd_output, sizeof atcmd_output, "%s %d %d", sd->mapname, sd->bl.x, sd->bl.y); - clif_displaymessage(fd, output); + clif_displaymessage(fd, atcmd_output); return -1; } - snprintf(output, sizeof output, "%s %s %d %d", - character, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y); - clif_displaymessage(fd, output); - + snprintf(atcmd_output, sizeof atcmd_output, "%s %s %d %d", + atcmd_player_name, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y); + clif_displaymessage(fd, atcmd_output); + return 0; } @@ -1097,35 +1152,33 @@ int atcommand_jumpto( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; - char output[200]; struct map_session_data *pl_sd = NULL; nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @jumpto/@warpto/@goto <char name>)."); return -1; } - - memset(character, '\0', sizeof character); - if (sscanf(message, "%99[^\n]", character) < 1) + + memset(atcmd_player_name, '\0', sizeof atcmd_player_name); + if (sscanf(message, "%99[^\n]", atcmd_player_name) < 1) return -1; - if(strncmp(sd->status.name,character,24)==0) //Yourself mate? Tsk tsk tsk. + if(strncmp(sd->status.name,atcmd_player_name,24)==0) //Yourself mate? Tsk tsk tsk. return -1; - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp you to the map of this player."); + clif_displaymessage(fd, msg_table[247]); return -1; } if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp you from your actual map."); + clif_displaymessage(fd, msg_table[248]); return -1; } pc_setpos(sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y, 3); - sprintf(output, msg_table[4], character); // Jump to %s - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[4], atcmd_player_name); // Jump to %s + clif_displaymessage(fd, atcmd_output); } else { clif_displaymessage(fd, msg_table[3]); // Character not found. return -1; @@ -1142,10 +1195,11 @@ int atcommand_jump( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char output[200]; int x = 0, y = 0; - memset(output, '\0', sizeof(output)); + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); sscanf(message, "%d %d", &x, &y); @@ -1154,17 +1208,13 @@ int atcommand_jump( if (y <= 0) y = rand() % 399 + 1; if (x > 0 && x < 400 && y > 0 && y < 400) { - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp you to your actual map."); - return -1; - } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp you from your actual map."); + if (sd->bl.m >= 0 && (map[sd->bl.m].flag.nowarp || map[sd->bl.m].flag.nowarpto) && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + clif_displaymessage(fd, msg_table[248]); return -1; } pc_setpos(sd, sd->mapname, x, y, 3); - sprintf(output, msg_table[5], x, y); // Jump to %d %d - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[5], x, y); // Jump to %d %d + clif_displaymessage(fd, atcmd_output); } else { clif_displaymessage(fd, msg_table[2]); // Coordinates out of range. return -1; @@ -1181,14 +1231,15 @@ int atcommand_who( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char output[200]; struct map_session_data *pl_sd; int i, j, count; int pl_GM_level, GM_level; char match_text[100]; char player_name[24]; - memset(output, '\0', sizeof(output)); + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(match_text, '\0', sizeof(match_text)); memset(player_name, '\0', sizeof(player_name)); @@ -1200,7 +1251,7 @@ int atcommand_who( count = 0; GM_level = pc_isGM(sd); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { pl_GM_level = pc_isGM(pl_sd); if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level memcpy(player_name, pl_sd->status.name, 24); @@ -1208,10 +1259,10 @@ int atcommand_who( player_name[j] = tolower(player_name[j]); if (strstr(player_name, match_text) != NULL) { // search with no case sensitive if (pl_GM_level > 0) - sprintf(output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_GM_level, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y); + sprintf(atcmd_output, "(CID:%d/AID:%d) Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.char_id, pl_sd->status.account_id, pl_sd->status.name, pl_GM_level, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y); else - sprintf(output, "Name: %s | Location: %s %d %d", pl_sd->status.name, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "(CID:%d/AID:%d) Name: %s | Location: %s %d %d", pl_sd->status.char_id, pl_sd->status.account_id, pl_sd->status.name, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y); + clif_displaymessage(fd, atcmd_output); count++; } } @@ -1223,8 +1274,8 @@ int atcommand_who( else if (count == 1) clif_displaymessage(fd, msg_table[29]); // 1 player found. else { - sprintf(output, msg_table[30], count); // %d players found. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[30], count); // %d players found. + clif_displaymessage(fd, atcmd_output); } return 0; @@ -1238,14 +1289,15 @@ int atcommand_who2( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char output[200]; struct map_session_data *pl_sd; int i, j, count; int pl_GM_level, GM_level; char match_text[100]; char player_name[24]; - memset(output, '\0', sizeof(output)); + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(match_text, '\0', sizeof(match_text)); memset(player_name, '\0', sizeof(player_name)); @@ -1257,7 +1309,7 @@ int atcommand_who2( count = 0; GM_level = pc_isGM(sd); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { pl_GM_level = pc_isGM(pl_sd); if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level memcpy(player_name, pl_sd->status.name, 24); @@ -1265,10 +1317,10 @@ int atcommand_who2( player_name[j] = tolower(player_name[j]); if (strstr(player_name, match_text) != NULL) { // search with no case sensitive if (pl_GM_level > 0) - sprintf(output, "Name: %s (GM:%d) | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_GM_level, pl_sd->status.base_level, job_name(pl_sd->status.class), pl_sd->status.job_level); + sprintf(atcmd_output, "Name: %s (GM:%d) | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_GM_level, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level); else - sprintf(output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class), pl_sd->status.job_level); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level); + clif_displaymessage(fd, atcmd_output); count++; } } @@ -1280,8 +1332,8 @@ int atcommand_who2( else if (count == 1) clif_displaymessage(fd, msg_table[29]); // 1 player found. else { - sprintf(output, msg_table[30], count); // %d players found. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[30], count); // %d players found. + clif_displaymessage(fd, atcmd_output); } return 0; @@ -1297,7 +1349,6 @@ int atcommand_who3( { char temp0[100]; char temp1[100]; - char output[200]; struct map_session_data *pl_sd; int i, j, count; int pl_GM_level, GM_level; @@ -1306,9 +1357,11 @@ int atcommand_who3( struct guild *g; struct party *p; + nullpo_retr(-1, sd); + memset(temp0, '\0', sizeof(temp0)); memset(temp1, '\0', sizeof(temp1)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(match_text, '\0', sizeof(match_text)); memset(player_name, '\0', sizeof(player_name)); @@ -1320,7 +1373,7 @@ int atcommand_who3( count = 0; GM_level = pc_isGM(sd); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { pl_GM_level = pc_isGM(pl_sd); if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level memcpy(player_name, pl_sd->status.name, 24); @@ -1338,10 +1391,10 @@ int atcommand_who3( else sprintf(temp0, "%s", p->name); if (pl_GM_level > 0) - sprintf(output, "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'", pl_sd->status.name, pl_GM_level, temp0, temp1); + sprintf(atcmd_output, "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'", pl_sd->status.name, pl_GM_level, temp0, temp1); else - sprintf(output, "Name: %s | Party: '%s' | Guild: '%s'", pl_sd->status.name, temp0, temp1); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Name: %s | Party: '%s' | Guild: '%s'", pl_sd->status.name, temp0, temp1); + clif_displaymessage(fd, atcmd_output); count++; } } @@ -1353,8 +1406,8 @@ int atcommand_who3( else if (count == 1) clif_displaymessage(fd, msg_table[29]); // 1 player found. else { - sprintf(output, msg_table[30], count); // %d players found. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[30], count); // %d players found. + clif_displaymessage(fd, atcmd_output); } return 0; @@ -1368,14 +1421,13 @@ int atcommand_whomap( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char output[200]; struct map_session_data *pl_sd; int i, count; int pl_GM_level, GM_level; int map_id; char map_name[100]; - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(map_name, '\0', sizeof(map_name)); if (!message || !*message) @@ -1391,15 +1443,15 @@ int atcommand_whomap( count = 0; GM_level = pc_isGM(sd); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { pl_GM_level = pc_isGM(pl_sd); if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level if (pl_sd->bl.m == map_id) { if (pl_GM_level > 0) - sprintf(output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_GM_level, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y); + sprintf(atcmd_output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_GM_level, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y); else - sprintf(output, "Name: %s | Location: %s %d %d", pl_sd->status.name, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Name: %s | Location: %s %d %d", pl_sd->status.name, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y); + clif_displaymessage(fd, atcmd_output); count++; } } @@ -1407,13 +1459,13 @@ int atcommand_whomap( } if (count == 0) - sprintf(output, msg_table[54], map[map_id].name); // No player found in map '%s'. + sprintf(atcmd_output, msg_table[54], map[map_id].name); // No player found in map '%s'. else if (count == 1) - sprintf(output, msg_table[55], map[map_id].name); // 1 player found in map '%s'. + sprintf(atcmd_output, msg_table[55], map[map_id].name); // 1 player found in map '%s'. else { - sprintf(output, msg_table[56], count, map[map_id].name); // %d players found in map '%s'. + sprintf(atcmd_output, msg_table[56], count, map[map_id].name); // %d players found in map '%s'. } - clif_displaymessage(fd, output); + clif_displaymessage(fd, atcmd_output); return 0; } @@ -1426,14 +1478,15 @@ int atcommand_whomap2( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char output[200]; struct map_session_data *pl_sd; int i, count; int pl_GM_level, GM_level; int map_id = 0; char map_name[100]; - memset(output, '\0', sizeof(output)); + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(map_name, '\0', sizeof(map_name)); if (!message || !*message) @@ -1449,15 +1502,15 @@ int atcommand_whomap2( count = 0; GM_level = pc_isGM(sd); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { pl_GM_level = pc_isGM(pl_sd); if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level if (pl_sd->bl.m == map_id) { if (pl_GM_level > 0) - sprintf(output, "Name: %s (GM:%d) | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_GM_level, pl_sd->status.base_level, job_name(pl_sd->status.class), pl_sd->status.job_level); + sprintf(atcmd_output, "Name: %s (GM:%d) | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_GM_level, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level); else - sprintf(output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class), pl_sd->status.job_level); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level); + clif_displaymessage(fd, atcmd_output); count++; } } @@ -1465,13 +1518,13 @@ int atcommand_whomap2( } if (count == 0) - sprintf(output, msg_table[54], map[map_id].name); // No player found in map '%s'. + sprintf(atcmd_output, msg_table[54], map[map_id].name); // No player found in map '%s'. else if (count == 1) - sprintf(output, msg_table[55], map[map_id].name); // 1 player found in map '%s'. + sprintf(atcmd_output, msg_table[55], map[map_id].name); // 1 player found in map '%s'. else { - sprintf(output, msg_table[56], count, map[map_id].name); // %d players found in map '%s'. + sprintf(atcmd_output, msg_table[56], count, map[map_id].name); // %d players found in map '%s'. } - clif_displaymessage(fd, output); + clif_displaymessage(fd, atcmd_output); return 0; } @@ -1486,7 +1539,6 @@ int atcommand_whomap3( { char temp0[100]; char temp1[100]; - char output[200]; struct map_session_data *pl_sd; int i, count; int pl_GM_level, GM_level; @@ -1495,9 +1547,11 @@ int atcommand_whomap3( struct guild *g; struct party *p; + nullpo_retr(-1, sd); + memset(temp0, '\0', sizeof(temp0)); memset(temp1, '\0', sizeof(temp1)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(map_name, '\0', sizeof(map_name)); if (!message || !*message) @@ -1513,7 +1567,7 @@ int atcommand_whomap3( count = 0; GM_level = pc_isGM(sd); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { pl_GM_level = pc_isGM(pl_sd); if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level if (pl_sd->bl.m == map_id) { @@ -1528,10 +1582,10 @@ int atcommand_whomap3( else sprintf(temp0, "%s", p->name); if (pl_GM_level > 0) - sprintf(output, "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'", pl_sd->status.name, pl_GM_level, temp0, temp1); + sprintf(atcmd_output, "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'", pl_sd->status.name, pl_GM_level, temp0, temp1); else - sprintf(output, "Name: %s | Party: '%s' | Guild: '%s'", pl_sd->status.name, temp0, temp1); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Name: %s | Party: '%s' | Guild: '%s'", pl_sd->status.name, temp0, temp1); + clif_displaymessage(fd, atcmd_output); count++; } } @@ -1539,13 +1593,13 @@ int atcommand_whomap3( } if (count == 0) - sprintf(output, msg_table[54], map[map_id].name); // No player found in map '%s'. + sprintf(atcmd_output, msg_table[54], map[map_id].name); // No player found in map '%s'. else if (count == 1) - sprintf(output, msg_table[55], map[map_id].name); // 1 player found in map '%s'. + sprintf(atcmd_output, msg_table[55], map[map_id].name); // 1 player found in map '%s'. else { - sprintf(output, msg_table[56], count, map[map_id].name); // %d players found in map '%s'. + sprintf(atcmd_output, msg_table[56], count, map[map_id].name); // %d players found in map '%s'. } - clif_displaymessage(fd, output); + clif_displaymessage(fd, atcmd_output); return 0; } @@ -1560,7 +1614,6 @@ int atcommand_whogm( { char temp0[100]; char temp1[100]; - char output[200]; struct map_session_data *pl_sd; int i, j, count; int pl_GM_level, GM_level; @@ -1569,9 +1622,11 @@ int atcommand_whogm( struct guild *g; struct party *p; + nullpo_retr(-1, sd); + memset(temp0, '\0', sizeof(temp0)); memset(temp1, '\0', sizeof(temp1)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(match_text, '\0', sizeof(match_text)); memset(player_name, '\0', sizeof(player_name)); @@ -1583,7 +1638,7 @@ int atcommand_whogm( count = 0; GM_level = pc_isGM(sd); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { pl_GM_level = pc_isGM(pl_sd); if (pl_GM_level > 0) { if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level @@ -1591,10 +1646,10 @@ int atcommand_whogm( for (j = 0; player_name[j]; j++) player_name[j] = tolower(player_name[j]); if (strstr(player_name, match_text) != NULL) { // search with no case sensitive - sprintf(output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_GM_level, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y); - clif_displaymessage(fd, output); - sprintf(output, " BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.base_level, job_name(pl_sd->status.class), pl_sd->status.job_level); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_GM_level, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, " BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level); + clif_displaymessage(fd, atcmd_output); g = guild_search(pl_sd->status.guild_id); if (g == NULL) sprintf(temp1, "None"); @@ -1605,8 +1660,8 @@ int atcommand_whogm( sprintf(temp0, "None"); else sprintf(temp0, "%s", p->name); - sprintf(output, " Party: '%s' | Guild: '%s'", temp0, temp1); - clif_displaymessage(fd, output); + sprintf(atcmd_output, " Party: '%s' | Guild: '%s'", temp0, temp1); + clif_displaymessage(fd, atcmd_output); count++; } } @@ -1619,8 +1674,8 @@ int atcommand_whogm( else if (count == 1) clif_displaymessage(fd, msg_table[151]); // 1 GM found. else { - sprintf(output, msg_table[152], count); // %d GMs found. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[152], count); // %d GMs found. + clif_displaymessage(fd, atcmd_output); } return 0; @@ -1630,15 +1685,18 @@ int atcommand_whozeny( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char output[200]; struct map_session_data *pl_sd; int i, j, count,c; char match_text[100]; char player_name[24]; - int zeny[clif_countusers()]; - int counted[clif_countusers()]; + //int zeny[clif_countusers()]; + //int counted[clif_countusers()]; + int *zeny = (int *)aCallocA(clif_countusers(), sizeof(int)); + int *counted = (int *)aCallocA(clif_countusers(), sizeof(int)); + + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(match_text, '\0', sizeof(match_text)); memset(player_name, '\0', sizeof(player_name)); @@ -1649,7 +1707,7 @@ int atcommand_whozeny( count = 0; for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { memcpy(player_name, pl_sd->status.name, 24); for (j = 0; player_name[j]; j++) player_name[j] = tolower(player_name[j]); @@ -1668,10 +1726,10 @@ int atcommand_whozeny( for (i = 0; i < fd_max; i++) { if(!zeny[c]) continue; - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && zeny[c] && counted[i]==0) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && zeny[c] && counted[i]==0) { if(pl_sd->status.zeny==zeny[c]) { - sprintf(output, "Name: %s | Zeny: %d", pl_sd->status.name, pl_sd->status.zeny); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Name: %s | Zeny: %d", pl_sd->status.name, pl_sd->status.zeny); + clif_displaymessage(fd, atcmd_output); zeny[c]=0; counted[i]=1; } @@ -1684,10 +1742,13 @@ int atcommand_whozeny( else if (count == 1) clif_displaymessage(fd, msg_table[29]); // 1 player found. else { - sprintf(output, msg_table[30], count); // %d players found. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[30], count); // %d players found. + clif_displaymessage(fd, atcmd_output); } + aFree(zeny); + aFree(counted); + return 0; } @@ -1697,14 +1758,15 @@ int atcommand_happyhappyjoyjoy( const int fd, struct map_session_data* sd, const char* command, const char* message) { - struct map_session_data *pl_sd; int i,e; + nullpo_retr(-1, sd); + for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { e=rand()%40; - if(e==34) + if(e==34) e = 0; clif_emotion(&pl_sd->bl,e); } @@ -1721,6 +1783,8 @@ int atcommand_save( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); + pc_setsavepoint(sd, sd->mapname, sd->bl.x, sd->bl.y); if (sd->status.pet_id > 0 && sd->pd) intif_save_petdata(sd->status.account_id, &sd->pet); @@ -1742,13 +1806,15 @@ int atcommand_load( { int m; + nullpo_retr(-1, sd); + m = map_mapname2mapid(sd->status.save_point.map); if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp you to your save map."); + clif_displaymessage(fd, msg_table[249]); return -1; } if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp you from your actual map."); + clif_displaymessage(fd, msg_table[248]); return -1; } @@ -1766,14 +1832,15 @@ int atcommand_speed( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char output[200]; int speed; - memset(output, '\0', sizeof(output)); + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message) { - sprintf(output, "Please, enter a speed value (usage: @speed <%d-%d>).", MIN_WALK_SPEED, MAX_WALK_SPEED); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Please, enter a speed value (usage: @speed <%d-%d>).", MIN_WALK_SPEED, MAX_WALK_SPEED); + clif_displaymessage(fd, atcmd_output); return -1; } @@ -1785,8 +1852,8 @@ int atcommand_speed( clif_updatestatus(sd, SP_SPEED); clif_displaymessage(fd, msg_table[8]); // Speed changed. } else { - sprintf(output, "Please, enter a valid speed value (usage: @speed <%d-%d>).", MIN_WALK_SPEED, MAX_WALK_SPEED); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Please, enter a valid speed value (usage: @speed <%d-%d>).", MIN_WALK_SPEED, MAX_WALK_SPEED); + clif_displaymessage(fd, atcmd_output); return -1; } @@ -1801,11 +1868,25 @@ int atcommand_storage( const int fd, struct map_session_data* sd, const char* command, const char* message) { + struct storage *stor; //changes from Freya/Yor + nullpo_retr(-1, sd); + + if (sd->state.storage_flag == 1) { + clif_displaymessage(fd, msg_table[250]); + return -1; + } + + if ((stor = account2storage2(sd->status.account_id)) != NULL && stor->storage_status == 1) { + clif_displaymessage(fd, msg_table[250]); + return -1; + } + storage_storageopen(sd); return 0; } + /*========================================== * *------------------------------------------ @@ -1814,8 +1895,23 @@ int atcommand_guildstorage( const int fd, struct map_session_data* sd, const char* command, const char* message) { - if (sd->status.guild_id > 0) + struct storage *stor; //changes from Freya/Yor + nullpo_retr(-1, sd); + + if (sd->status.guild_id > 0) { + if (sd->state.storage_flag == 1) { + clif_displaymessage(fd, msg_table[251]); + return -1; + } + if ((stor = account2storage2(sd->status.account_id)) != NULL && stor->storage_status == 1) { + clif_displaymessage(fd, msg_table[251]); + return -1; + } storage_guild_storageopen(sd); + } else { + clif_displaymessage(fd, msg_table[252]); + return -1; + } return 0; } @@ -1829,6 +1925,7 @@ int atcommand_option( const char* command, const char* message) { int param1 = 0, param2 = 0, param3 = 0; + nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d %d %d", ¶m1, ¶m2, ¶m3) < 1 || param1 < 0 || param2 < 0 || param3 < 0) { clif_displaymessage(fd, "Please, enter at least a option (usage: @option <param1:0+> <param2:0+> <param3:0+>)."); @@ -1844,30 +1941,30 @@ int atcommand_option( } sd->status.option = param3; // fix pecopeco display - if (sd->status.class == 13 || sd->status.class == 21 || sd->status.class == 4014 || sd->status.class == 4022) { + if (sd->status.class_ == 13 || sd->status.class_ == 21 || sd->status.class_ == 4014 || sd->status.class_ == 4022) { if (!pc_isriding(sd)) { // sd have the new value... - if (sd->status.class == 13) - sd->status.class = sd->view_class = 7; - else if (sd->status.class == 21) - sd->status.class = sd->view_class = 14; - else if (sd->status.class == 4014) - sd->status.class = sd->view_class = 4008; - else if (sd->status.class == 4022) - sd->status.class = sd->view_class = 4015; + if (sd->status.class_ == 13) + sd->status.class_ = sd->view_class = 7; + else if (sd->status.class_ == 21) + sd->status.class_ = sd->view_class = 14; + else if (sd->status.class_ == 4014) + sd->status.class_ = sd->view_class = 4008; + else if (sd->status.class_ == 4022) + sd->status.class_ = sd->view_class = 4015; } } else { if (pc_isriding(sd)) { // sd have the new value... if (sd->disguise > 0) { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris] (code added by [Yor]) sd->status.option &= ~0x0020; } else { - if (sd->status.class == 7) - sd->status.class = sd->view_class = 13; - else if (sd->status.class == 14) - sd->status.class = sd->view_class = 21; - else if (sd->status.class == 4008) - sd->status.class = sd->view_class = 4014; - else if (sd->status.class == 4015) - sd->status.class = sd->view_class = 4022; + if (sd->status.class_ == 7) + sd->status.class_ = sd->view_class = 13; + else if (sd->status.class_ == 14) + sd->status.class_ = sd->view_class = 21; + else if (sd->status.class_ == 4008) + sd->status.class_ = sd->view_class = 4014; + else if (sd->status.class_ == 4015) + sd->status.class_ = sd->view_class = 4022; else sd->status.option &= ~0x0020; } @@ -1875,7 +1972,7 @@ int atcommand_option( } clif_changeoption(&sd->bl); - pc_calcstatus(sd, 0); + status_calc_pc(sd, 0); clif_displaymessage(fd, msg_table[9]); // Options changed. return 0; @@ -1889,6 +1986,7 @@ int atcommand_hide( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); if (sd->status.option & OPTION_HIDE) { sd->status.option &= ~OPTION_HIDE; clif_displaymessage(fd, msg_table[10]); // Invisible: Off @@ -1909,32 +2007,116 @@ int atcommand_jobchange( const int fd, struct map_session_data* sd, const char* command, const char* message) { - int job = 0, upper = -1; + int job = 0, upper = 0; + nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d %d", &job, &upper) < 1) { - clif_displaymessage(fd, "Please, enter job ID (usage: @job/@jobchange <job ID>)."); - return -1; + + int i, found = 0; + const struct { char name[16]; int id; } jobs[] = { + { "novice", 0 }, + { "swordsman", 1 }, + { "mage", 2 }, + { "archer", 3 }, + { "acolyte", 4 }, + { "merchant", 5 }, + { "thief", 6 }, + { "knight", 7 }, + { "priest", 8 }, + { "priestess", 8 }, + { "wizard", 9 }, + { "blacksmith", 10 }, + { "hunter", 11 }, + { "assassin", 12 }, + { "crusader", 14 }, + { "monk", 15 }, + { "sage", 16 }, + { "rogue", 17 }, + { "alchemist", 18 }, + { "bard", 19 }, + { "dancer", 20 }, + { "super novice", 23 }, + { "supernovice", 23 }, + { "high novice", 4001 }, + { "swordsman high", 4002 }, + { "mage high", 4003 }, + { "archer high", 4004 }, + { "acolyte high", 4005 }, + { "merchant high", 4006 }, + { "thief high", 4007 }, + { "lord knight", 4008 }, + { "high priest", 4009 }, + { "high priestess", 4009 }, + { "high wizard", 4010 }, + { "whitesmith", 4011 }, + { "sniper", 4012 }, + { "assassin cross", 4013 }, + { "paladin", 4015 }, + { "champion", 4016 }, + { "professor", 4017 }, + { "stalker", 4018 }, + { "creator", 4019 }, + { "clown", 4020 }, + { "gypsy", 4021 }, + { "baby novice", 4023 }, + { "baby swordsman", 4024 }, + { "baby mage", 4025 }, + { "baby archer", 4026 }, + { "baby acolyte", 4027 }, + { "baby merchant", 4028 }, + { "baby thief", 4029 }, + { "baby knight", 4030 }, + { "baby priest", 4031 }, + { "baby priestess", 4031 }, + { "baby wizard", 4032 }, + { "baby blacksmith",4033 }, + { "baby hunter", 4034 }, + { "baby assassin", 4035 }, + { "baby crusader", 4037 }, + { "baby monk", 4038 }, + { "baby sage", 4039 }, + { "baby rogue", 4040 }, + { "baby alchemist", 4041 }, + { "baby bard", 4042 }, + { "baby dancer", 4043 }, + { "super baby", 4045 }, + }; + + for (i=0; i < (int)(sizeof(jobs) / sizeof(jobs[0])); i++) { + if (strncmpi(message, jobs[i].name, 16) == 0) { + job = jobs[i].id; + upper = 0; + found = 1; + break; + } + } + + if (!found) { + clif_displaymessage(fd, "Please, enter job ID (usage: @job/@jobchange <job ID>)."); + return -1; + } } if (job == 37 ||job == 45) return 0; if ((job >= 0 && job < MAX_PC_CLASS)) { + int j; // fix pecopeco display if ((job != 13 && job != 21 && job != 4014 && job != 4022)) { if (pc_isriding(sd)) { - if (sd->status.class == 13) - sd->status.class = sd->view_class = 7; - if (sd->status.class == 21) - sd->status.class = sd->view_class = 14; - if (sd->status.class == 4014) - sd->status.class = sd->view_class = 4008; - if (sd->status.class == 4022) - sd->status.class = sd->view_class = 4015; + if (sd->status.class_ == 13) + sd->status.class_ = sd->view_class = 7; + if (sd->status.class_ == 21) + sd->status.class_ = sd->view_class = 14; + if (sd->status.class_ == 4014) + sd->status.class_ = sd->view_class = 4008; + if (sd->status.class_ == 4022) + sd->status.class_ = sd->view_class = 4015; sd->status.option &= ~0x0020; clif_changeoption(&sd->bl); - pc_calcstatus(sd, 0); + status_calc_pc(sd, 0); } } else { if (!pc_isriding(sd)) { @@ -1948,7 +2130,10 @@ int atcommand_jobchange( job = 4015; } } - + for (j=0; j < MAX_INVENTORY; j++) { + if(sd->status.inventory[j].nameid>0 && sd->status.inventory[j].equip!=0) + pc_unequipitem(sd, j, 3); + } if (pc_jobchange(sd, job, upper) == 0) clif_displaymessage(fd, msg_table[12]); // Your job has been changed. else { @@ -1971,6 +2156,7 @@ int atcommand_die( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); clif_specialeffect(&sd->bl,450,1); pc_damage(NULL, sd, sd->status.hp + 1); clif_displaymessage(fd, msg_table[13]); // A pity! You've died. @@ -1986,17 +2172,17 @@ int atcommand_kill( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; struct map_session_data *pl_sd; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @kill <char name>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kill only lower or same level pc_damage(NULL, pl_sd, pl_sd->status.hp + 1); clif_displaymessage(fd, msg_table[14]); // Character killed. @@ -2020,6 +2206,7 @@ int atcommand_alive( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); if (pc_isdead(sd)) { sd->status.hp = sd->status.max_hp; sd->status.sp = sd->status.max_sp; @@ -2032,9 +2219,8 @@ int atcommand_alive( clif_resurrection(&sd->bl, 1); clif_displaymessage(fd, msg_table[16]); // You've been revived! It's a miracle! return 0; - } + } return -1; - } /*========================================== @@ -2045,17 +2231,17 @@ int atcommand_kami( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char output[200]; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message) { clif_displaymessage(fd, "Please, enter a message (usage: @kami <message>)."); return -1; } - sscanf(message, "%199[^\n]", output); - intif_GMmessage(output, strlen(output) + 1, (*(command + 5) == 'b') ? 0x10 : 0); + sscanf(message, "%199[^\n]", atcmd_output); + intif_GMmessage(atcmd_output, strlen(atcmd_output) + 1, (*(command + 5) == 'b') ? 0x10 : 0); return 0; } @@ -2069,6 +2255,7 @@ int atcommand_heal( const char* command, const char* message) { int hp = 0, sp = 0; // [Valaris] thanks to fov + nullpo_retr(-1, sd); sscanf(message, "%d %d", &hp, &sp); @@ -2120,6 +2307,7 @@ int atcommand_item( struct item item_tmp; struct item_data *item_data; int get_count, i, pet_id; + nullpo_retr(-1, sd); memset(item_name, '\0', sizeof(item_name)); @@ -2147,10 +2335,10 @@ int atcommand_item( for (i = 0; i < number; i += get_count) { // if pet egg if (pet_id >= 0) { - sd->catch_target_class = pet_db[pet_id].class; + sd->catch_target_class = pet_db[pet_id].class_; intif_create_pet(sd->status.account_id, sd->status.char_id, - pet_db[pet_id].class, mob_db[pet_db[pet_id].class].lv, - pet_db[pet_id].EggID, 0, pet_db[pet_id].intimate, + (short)pet_db[pet_id].class_, (short)mob_db[pet_db[pet_id].class_].lv, + (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate, 100, 0, 1, pet_db[pet_id].jname); // if not pet egg } else { @@ -2186,6 +2374,7 @@ int atcommand_item2( int c1 = 0, c2 = 0, c3 = 0, c4 = 0; int flag; int loop, get_count, i; + nullpo_retr(-1, sd); memset(item_name, '\0', sizeof(item_name)); @@ -2253,6 +2442,7 @@ int atcommand_itemreset( const char* command, const char* message) { int i; + nullpo_retr(-1, sd); for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].amount && sd->status.inventory[i].equip == 0) @@ -2271,6 +2461,7 @@ int atcommand_itemcheck( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); pc_checkitem(sd); return 0; @@ -2285,6 +2476,7 @@ int atcommand_baselevelup( const char* command, const char* message) { int level, i; + nullpo_retr(-1, sd); if (!message || !*message || (level = atoi(message)) == 0) { clif_displaymessage(fd, "Please, enter a level adjustement (usage: @lvup/@blevel/@baselvlup <number of levels>)."); @@ -2296,7 +2488,7 @@ int atcommand_baselevelup( clif_displaymessage(fd, msg_table[47]); // Base level can't go any higher. return -1; } // End Addition - if (level > battle_config.maximum_level || level > (battle_config.maximum_level - sd->status.base_level)) // fix positiv overflow + if ((unsigned int)level > battle_config.maximum_level || (unsigned int)level > (battle_config.maximum_level - sd->status.base_level)) // fix positiv overflow level = battle_config.maximum_level - sd->status.base_level; for (i = 1; i <= level; i++) sd->status.status_point += (sd->status.base_level + i + 14) / 5; @@ -2304,7 +2496,7 @@ int atcommand_baselevelup( clif_updatestatus(sd, SP_BASELEVEL); clif_updatestatus(sd, SP_NEXTBASEEXP); clif_updatestatus(sd, SP_STATUSPOINT); - pc_calcstatus(sd, 0); + status_calc_pc(sd, 0); pc_heal(sd, sd->status.max_hp, sd->status.max_sp); clif_misceffect(&sd->bl, 0); clif_displaymessage(fd, msg_table[21]); // Base level raised. @@ -2313,7 +2505,7 @@ int atcommand_baselevelup( clif_displaymessage(fd, msg_table[158]); // Base level can't go any lower. return -1; } - if (level < -battle_config.maximum_level || level < (1 - sd->status.base_level)) // fix negativ overflow + if (level < -(int)battle_config.maximum_level || level < (1 - (int)sd->status.base_level)) // fix negativ overflow level = 1 - sd->status.base_level; if (sd->status.status_point > 0) { for (i = 0; i > level; i--) @@ -2325,7 +2517,7 @@ int atcommand_baselevelup( sd->status.base_level += level; clif_updatestatus(sd, SP_BASELEVEL); clif_updatestatus(sd, SP_NEXTBASEEXP); - pc_calcstatus(sd, 0); + status_calc_pc(sd, 0); clif_displaymessage(fd, msg_table[22]); // Base level lowered. } @@ -2340,16 +2532,23 @@ int atcommand_joblevelup( const int fd, struct map_session_data* sd, const char* command, const char* message) { - int up_level = 50, level; + unsigned int up_level = 50; + int level; + struct pc_base_job s_class; + nullpo_retr(-1, sd); + s_class = pc_calc_base_job(sd->status.class_); if (!message || !*message || (level = atoi(message)) == 0) { clif_displaymessage(fd, "Please, enter a level adjustement (usage: @joblvup/@jlevel/@joblvlup <number of levels>)."); return -1; } - if (sd->status.class == 0 || sd->status.class == 4001) + if (s_class.job == 0) up_level -= 40; - else if ((sd->status.class > 4007 && sd->status.class < 4024) || sd->status.class == 23) + // super novices can go up to 99 [celest] + else if (s_class.job == 23) + up_level += 49; + else if (sd->status.class_ > 4007 && sd->status.class_ < 4023) up_level += 20; if (level > 0) { @@ -2357,14 +2556,14 @@ int atcommand_joblevelup( clif_displaymessage(fd, msg_table[23]); // Job level can't go any higher. return -1; } - if (level > up_level || level > (up_level - sd->status.job_level)) // fix positiv overflow + if ((unsigned int)level > up_level || (unsigned int)level > (up_level - sd->status.job_level)) // fix positiv overflow level = up_level - sd->status.job_level; sd->status.job_level += level; clif_updatestatus(sd, SP_JOBLEVEL); clif_updatestatus(sd, SP_NEXTJOBEXP); sd->status.skill_point += level; clif_updatestatus(sd, SP_SKILLPOINT); - pc_calcstatus(sd, 0); + status_calc_pc(sd, 0); clif_misceffect(&sd->bl, 1); clif_displaymessage(fd, msg_table[24]); // Job level raised. } else { @@ -2372,7 +2571,7 @@ int atcommand_joblevelup( clif_displaymessage(fd, msg_table[159]); // Job level can't go any lower. return -1; } - if (level < -up_level || level < (1 - sd->status.job_level)) // fix negativ overflow + if (level < -(int)up_level || level < (1 - (int)sd->status.job_level)) // fix negativ overflow level = 1 - sd->status.job_level; sd->status.job_level += level; clif_updatestatus(sd, SP_JOBLEVEL); @@ -2383,7 +2582,7 @@ int atcommand_joblevelup( sd->status.skill_point = 0; clif_updatestatus(sd, SP_SKILLPOINT); } // to add: remove status points from skills - pc_calcstatus(sd, 0); + status_calc_pc(sd, 0); clif_displaymessage(fd, msg_table[25]); // Job level lowered. } @@ -2401,6 +2600,7 @@ int atcommand_help( char buf[2048], w1[2048], w2[2048]; int i, gm_level; FILE* fp; + nullpo_retr(-1, sd); memset(buf, '\0', sizeof(buf)); @@ -2439,6 +2639,7 @@ int atcommand_gm( const char* command, const char* message) { char password[100]; + nullpo_retr(-1, sd); memset(password, '\0', sizeof(password)); @@ -2466,6 +2667,7 @@ int atcommand_pvpoff( { struct map_session_data *pl_sd; int i; + nullpo_retr(-1, sd); if (battle_config.pk_mode) { //disable command if server is in PK mode [Valaris] clif_displaymessage(fd, msg_table[52]); // This option cannot be used in PK Mode. @@ -2476,7 +2678,7 @@ int atcommand_pvpoff( map[sd->bl.m].flag.pvp = 0; clif_send0199(sd->bl.m, 0); for (i = 0; i < fd_max; i++) { //l”•ªƒ‹[ƒv - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { if (sd->bl.m == pl_sd->bl.m) { clif_pvpset(pl_sd, 0, 0, 2); if (pl_sd->pvp_timer != -1) { @@ -2505,6 +2707,7 @@ int atcommand_pvpon( { struct map_session_data *pl_sd; int i; + nullpo_retr(-1, sd); if (battle_config.pk_mode) { //disable command if server is in PK mode [Valaris] clif_displaymessage(fd, msg_table[52]); // This option cannot be used in PK Mode. @@ -2515,7 +2718,7 @@ int atcommand_pvpon( map[sd->bl.m].flag.pvp = 1; clif_send0199(sd->bl.m, 1); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { if (sd->bl.m == pl_sd->bl.m && pl_sd->pvp_timer == -1) { pl_sd->pvp_timer = add_timer(gettick() + 200, pc_calc_pvprank_timer, pl_sd->bl.id, 0); @@ -2542,6 +2745,7 @@ int atcommand_gvgoff( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); if (map[sd->bl.m].flag.gvg) { map[sd->bl.m].flag.gvg = 0; clif_send0199(sd->bl.m, 0); @@ -2562,6 +2766,7 @@ int atcommand_gvgon( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); if (!map[sd->bl.m].flag.gvg) { map[sd->bl.m].flag.gvg = 1; clif_send0199(sd->bl.m, 3); @@ -2583,14 +2788,14 @@ int atcommand_model( const char* command, const char* message) { int hair_style = 0, hair_color = 0, cloth_color = 0; - char output[200]; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%d %d %d", &hair_style, &hair_color, &cloth_color) < 1) { - sprintf(output, "Please, enter at least a value (usage: @model <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d>).", + sprintf(atcmd_output, "Please, enter at least a value (usage: @model <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d>).", MIN_HAIR_STYLE, MAX_HAIR_STYLE, MIN_HAIR_COLOR, MAX_HAIR_COLOR, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); - clif_displaymessage(fd, output); + clif_displaymessage(fd, atcmd_output); return -1; } @@ -2598,7 +2803,7 @@ int atcommand_model( hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR && cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) { //•ž‚ÌF•ÏX - if (cloth_color != 0 && sd->status.sex == 1 && (sd->status.class == 12 || sd->status.class == 17)) { + if (cloth_color != 0 && sd->status.sex == 1 && (sd->status.class_ == 12 || sd->status.class_ == 17)) { //•ž‚ÌF–¢ŽÀ‘•E‚Ì”»’è clif_displaymessage(fd, msg_table[35]); // You can't use this command with this class. return -1; @@ -2623,24 +2828,19 @@ int atcommand_model( int atcommand_dye(const int fd, struct map_session_data* sd, const char* command, const char* message) { int cloth_color = 0; - char output[200]; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%d", &cloth_color) < 1) { - sprintf(output, "Please, enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>).", MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Please, enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>).", MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); + clif_displaymessage(fd, atcmd_output); return -1; } if (cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) { - if (cloth_color != 0 && sd->status.sex == 1 && (sd->status.class == 12 || sd->status.class == 17)) { - clif_displaymessage(fd, msg_table[35]); // You can't use this command with this class. - return -1; - } else { - pc_changelook(sd, LOOK_CLOTHES_COLOR, cloth_color); - clif_displaymessage(fd, msg_table[36]); // Appearence changed. - } + pc_changelook(sd, LOOK_CLOTHES_COLOR, cloth_color); + clif_displaymessage(fd, msg_table[36]); // Appearence changed. } else { clif_displaymessage(fd, msg_table[37]); // An invalid number was specified. return -1; @@ -2650,35 +2850,24 @@ int atcommand_dye(const int fd, struct map_session_data* sd, const char* command } /*========================================== - * @chardye by [MouseJstr] - *------------------------------------------ - */ -int -atcommand_chardye(const int fd, struct map_session_data* sd, - const char* command, const char* message) -{ - return 0; -} - -/*========================================== * @hairstyle && @hstyle *------------------------------------------ */ int atcommand_hair_style(const int fd, struct map_session_data* sd, const char* command, const char* message) { int hair_style = 0; - char output[200]; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%d", &hair_style) < 1) { - sprintf(output, "Please, enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>).", MIN_HAIR_STYLE, MAX_HAIR_STYLE); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Please, enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>).", MIN_HAIR_STYLE, MAX_HAIR_STYLE); + clif_displaymessage(fd, atcmd_output); return -1; } if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE) { - if (hair_style != 0 && sd->status.sex == 1 && (sd->status.class == 12 || sd->status.class == 17)) { + if (hair_style != 0 && sd->status.sex == 1 && (sd->status.class_ == 12 || sd->status.class_ == 17)) { clif_displaymessage(fd, msg_table[35]); // You can't use this command with this class. return -1; } else { @@ -2701,7 +2890,8 @@ int atcommand_charhairstyle(const int fd, struct map_session_data* sd, const char* command, const char* message) { - return 0; + nullpo_retr(-1, sd); + return 0; } /*========================================== @@ -2711,18 +2901,18 @@ atcommand_charhairstyle(const int fd, struct map_session_data* sd, int atcommand_hair_color(const int fd, struct map_session_data* sd, const char* command, const char* message) { int hair_color = 0; - char output[200]; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%d", &hair_color) < 1) { - sprintf(output, "Please, enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>).", MIN_HAIR_COLOR, MAX_HAIR_COLOR); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Please, enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>).", MIN_HAIR_COLOR, MAX_HAIR_COLOR); + clif_displaymessage(fd, atcmd_output); return -1; } if (hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR) { - if (hair_color != 0 && sd->status.sex == 1 && (sd->status.class == 12 || sd->status.class == 17)) { + if (hair_color != 0 && sd->status.sex == 1 && (sd->status.class_ == 12 || sd->status.class_ == 17)) { clif_displaymessage(fd, msg_table[35]); // You can't use this command with this class. return -1; } else { @@ -2738,17 +2928,6 @@ int atcommand_hair_color(const int fd, struct map_session_data* sd, const char* } /*========================================== - * @charhaircolor by [MouseJstr] - *------------------------------------------ - */ -int -atcommand_charhaircolor(const int fd, struct map_session_data* sd, - const char* command, const char* message) -{ - return 0; -} - -/*========================================== * @go [city_number/city_name]: improved by [yor] to add city names and help *------------------------------------------ */ @@ -2759,15 +2938,9 @@ int atcommand_go( int i; int town; char map_name[100]; - char output[200]; int m; - if(map[sd->bl.m].flag.nogo) { - clif_displaymessage(sd->fd,"You can not use @go on this map."); - return 0; - } - - struct { char map[16]; int x, y; } data[] = { + const struct { char map[16]; int x, y; } data[] = { { "prontera.gat", 156, 191 }, // 0=Prontera { "morocc.gat", 156, 93 }, // 1=Morroc { "geffen.gat", 119, 59 }, // 2=Geffen @@ -2785,10 +2958,19 @@ int atcommand_go( { "louyang.gat", 217, 40 }, // 14=Lou Yang { "new_1-1.gat", 53, 111 }, // 15=Start point { "sec_pri.gat", 23, 61 }, // 16=Prison + { "jawaii.gat", 249, 127 }, // 17=Jawaii + { "ayothaya.gat", 151, 117 }, // 18=Ayothaya }; + nullpo_retr(-1, sd); + + if(map[sd->bl.m].flag.nogo) { + clif_displaymessage(sd->fd,"You can not use @go on this map."); + return 0; + } + memset(map_name, '\0', sizeof(map_name)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); // get the number town = atoi(message); @@ -2803,7 +2985,8 @@ int atcommand_go( clif_displaymessage(fd, " 0=Prontera 7=Lutie 14=Lou Yang"); clif_displaymessage(fd, " 1=Morroc 8=Comodo 15=Start point"); clif_displaymessage(fd, " 2=Geffen 9=Yuno 16=Prison"); - clif_displaymessage(fd, " 3=Payon 10=Amatsu"); + clif_displaymessage(fd, " 3=Payon 10=Amatsu 17=Jawaii"); + clif_displaymessage(fd, " 18=Ayothaya"); return -1; } else { // get possible name of the city and add .gat if not in the name @@ -2858,17 +3041,23 @@ int atcommand_go( strncmp(map_name, "prison.gat", 3) == 0 || // name of the position (3 first characters) strncmp(map_name, "jails.gat", 3) == 0) { // name of the position town = 16; + } else if (strncmp(map_name, "jawaii.gat", 3) == 0 || // 3 first characters + strncmp(map_name, "jawai.gat", 3) == 0) { // writing error (3 first characters) + town = 17; + } else if (strncmp(map_name, "ayothaya.gat", 4) == 0 || // 3 first characters + strncmp(map_name, "ayotaya.gat", 4) == 0) { // writing error (3 first characters) + town = 18; } if (town >= -3 && town <= -1) { if (sd->status.memo_point[-town-1].map[0]) { m = map_mapname2mapid(sd->status.memo_point[-town-1].map); if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp you to this memo map."); + clif_displaymessage(fd, msg_table[247]); return -1; } if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp you from your actual map."); + clif_displaymessage(fd, msg_table[248]); return -1; } if (pc_setpos(sd, sd->status.memo_point[-town-1].map, sd->status.memo_point[-town-1].x, sd->status.memo_point[-town-1].y, 3) == 0) { @@ -2878,21 +3067,21 @@ int atcommand_go( return -1; } } else { - sprintf(output, msg_table[164], -town-1); // Your memo point #%d doesn't exist. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[164], -town-1); // Your memo point #%d doesn't exist. + clif_displaymessage(fd, atcmd_output); return -1; } } else if (town >= 0 && town < (int)(sizeof(data) / sizeof(data[0]))) { - m = map_mapname2mapid(data[town].map); + m = map_mapname2mapid((char *)data[town].map); if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp you to this destination map."); + clif_displaymessage(fd, msg_table[247]); return -1; } if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp you from your actual map."); + clif_displaymessage(fd, msg_table[248]); return -1; } - if (pc_setpos(sd, data[town].map, data[town].x, data[town].y, 3) == 0) { + if (pc_setpos(sd, (char *)data[town].map, data[town].x, data[town].y, 3) == 0) { clif_displaymessage(fd, msg_table[0]); // Warped. } else { clif_displaymessage(fd, msg_table[1]); // Map not found. @@ -2917,17 +3106,17 @@ int atcommand_monster( { char name[100]; char monster[100]; - char output[200]; int mob_id; int number = 0; int x = 0, y = 0; int count; int i, j, k; int mx, my, range; + nullpo_retr(-1, sd); memset(name, '\0', sizeof(name)); memset(monster, '\0', sizeof(monster)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || (sscanf(message, "\"%[^\"]\" %99s %d %d %d", name, monster, &number, &x, &y) < 2 && @@ -2964,7 +3153,7 @@ int atcommand_monster( printf("%s monster='%s' name='%s' id=%d count=%d (%d,%d)\n", command, monster, name, mob_id, number, x, y); count = 0; - range = sqrt(number) / 2; + range = (int)sqrt(number) / 2; range = range * 2 + 5; // calculation of an odd number (+ 4 area around) for (i = 0; i < number; i++) { j = 0; @@ -2987,8 +3176,8 @@ int atcommand_monster( if (number == count) clif_displaymessage(fd, msg_table[39]); // All monster summoned! else { - sprintf(output, msg_table[240], count); // %d monster(s) summoned! - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[240], count); // %d monster(s) summoned! + clif_displaymessage(fd, atcmd_output); } else { clif_displaymessage(fd, msg_table[40]); // Invalid monster ID or name. @@ -3007,7 +3196,6 @@ int atcommand_spawn( const char* command, const char* message) { char name[100]; char monster[100]; - char output[200]; int mob_id; int number = 0; int x = 0, y = 0; @@ -3015,9 +3203,10 @@ int atcommand_spawn( int i, j, k; int mx, my, range; + nullpo_retr(-1, sd); memset(name, '\0', sizeof(name)); memset(monster, '\0', sizeof(monster)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || (sscanf(message, "\"%[^\"]\" %99s %d %d %d", name, monster, &number, &x, &y) < 2 && @@ -3055,7 +3244,7 @@ int atcommand_spawn( printf("%s monster='%s' name='%s' id=%d count=%d (%d,%d)\n", command, monster, name, mob_id, number, x, y); count = 0; - range = sqrt(number) / 2; + range = (int)sqrt(number) / 2; range = range * 2 + 5; // calculation of an odd number (+ 4 area around) for (i = 0; i < number; i++) { j = 0; @@ -3078,8 +3267,8 @@ int atcommand_spawn( if (number == count) clif_displaymessage(fd, msg_table[39]); // All monster summoned! else { - sprintf(output, msg_table[240], count); // %d monster(s) summoned! - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[240], count); // %d monster(s) summoned! + clif_displaymessage(fd, atcmd_output); } else { clif_displaymessage(fd, msg_table[40]); // Invalid monster ID or name. @@ -3254,6 +3443,8 @@ void atcommand_killmonster_sub( int map_id; char map_name[100]; + if (!sd) return; + memset(map_name, '\0', sizeof(map_name)); if (!message || !*message || sscanf(message, "%99s", map_name) < 1) @@ -3280,6 +3471,7 @@ int atcommand_killmonster( const int fd, struct map_session_data* sd, const char* command, const char* message) { + if (!sd) return 0; atcommand_killmonster_sub(fd, sd, message, 1); return 0; @@ -3293,6 +3485,7 @@ int atcommand_killmonster2( const int fd, struct map_session_data* sd, const char* command, const char* message) { + if (!sd) return 0; atcommand_killmonster_sub(fd, sd, message, 0); return 0; @@ -3308,9 +3501,9 @@ int atcommand_refine( { int i, position = 0, refine = 0, current_position, final_refine; int count; - char output[200]; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%d %d", &position, &refine) < 2) { clif_displaymessage(fd, "Please, enter a position and a amount (usage: @refine <equip position> <+/- amount>)."); @@ -3337,7 +3530,7 @@ int atcommand_refine( if (sd->status.inventory[i].refine != final_refine) { sd->status.inventory[i].refine = final_refine; current_position = sd->status.inventory[i].equip; - pc_unequipitem(sd, i, 0, BF_NORMAL); + pc_unequipitem(sd, i, 3); clif_refine(fd, sd, 0, i, sd->status.inventory[i].refine); clif_delitem(sd, i, 1); clif_additem(sd, i, 1, 0); @@ -3353,8 +3546,8 @@ int atcommand_refine( else if (count == 1) clif_displaymessage(fd, msg_table[167]); // 1 item has been refined! else { - sprintf(output, msg_table[168], count); // %d items have been refined! - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[168], count); // %d items have been refined! + clif_displaymessage(fd, atcmd_output); } return 0; @@ -3373,9 +3566,9 @@ int atcommand_produce( int flag = 0; struct item_data *item_data; struct item tmp_item; - char output[200]; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(item_name, '\0', sizeof(item_name)); if (!message || !*message || sscanf(message, "%99s %d %d", item_name, &attribute, &star) < 1) { @@ -3412,10 +3605,10 @@ int atcommand_produce( if (battle_config.error_log) printf("@produce NOT WEAPON [%d]\n", item_id); if (item_id != 0 && itemdb_exists(item_id)) - sprintf(output, msg_table[169], item_id, item_data->name); // This item (%d: '%s') is not an equipment. + sprintf(atcmd_output, msg_table[169], item_id, item_data->name); // This item (%d: '%s') is not an equipment. else - sprintf(output, msg_table[170]); // This item is not an equipment. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[170]); // This item is not an equipment. + clif_displaymessage(fd, atcmd_output); return -1; } @@ -3428,17 +3621,18 @@ int atcommand_produce( */ void atcommand_memo_sub(struct map_session_data* sd) { int i; - char output[200]; - memset(output, '\0', sizeof(output)); + if (!sd) return; + + memset(atcmd_output, '\0', sizeof(atcmd_output)); clif_displaymessage(sd->fd, "Your actual memo positions are (except respawn point):"); for (i = MIN_PORTAL_MEMO; i <= MAX_PORTAL_MEMO; i++) { if (sd->status.memo_point[i].map[0]) - sprintf(output, "%d - %s (%d,%d)", i, sd->status.memo_point[i].map, sd->status.memo_point[i].x, sd->status.memo_point[i].y); + sprintf(atcmd_output, "%d - %s (%d,%d)", i, sd->status.memo_point[i].map, sd->status.memo_point[i].x, sd->status.memo_point[i].y); else - sprintf(output, msg_table[171], i); // %d - void - clif_displaymessage(sd->fd, output); + sprintf(atcmd_output, msg_table[171], i); // %d - void + clif_displaymessage(sd->fd, atcmd_output); } return; @@ -3453,21 +3647,21 @@ int atcommand_memo( const char* command, const char* message) { int position = 0; - char output[200]; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%d", &position) < 1) atcommand_memo_sub(sd); else { if (position >= MIN_PORTAL_MEMO && position <= MAX_PORTAL_MEMO) { if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to memo this map."); + clif_displaymessage(fd, msg_table[253]); return -1; } if (sd->status.memo_point[position].map[0]) { - sprintf(output, msg_table[172], position, sd->status.memo_point[position].map, sd->status.memo_point[position].x, sd->status.memo_point[position].y); // You replace previous memo position %d - %s (%d,%d). - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[172], position, sd->status.memo_point[position].map, sd->status.memo_point[position].x, sd->status.memo_point[position].y); // You replace previous memo position %d - %s (%d,%d). + clif_displaymessage(fd, atcmd_output); } memcpy(sd->status.memo_point[position].map, map[sd->bl.m].name, 24); sd->status.memo_point[position].x = sd->bl.x; @@ -3477,8 +3671,8 @@ int atcommand_memo( clif_displaymessage(fd, msg_table[173]); // Note: you don't have the 'Warp' skill level to use it. atcommand_memo_sub(sd); } else { - sprintf(output, "Please, enter a valid position (usage: @memo <memo_position:%d-%d>).", MIN_PORTAL_MEMO, MAX_PORTAL_MEMO); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Please, enter a valid position (usage: @memo <memo_position:%d-%d>).", MIN_PORTAL_MEMO, MAX_PORTAL_MEMO); + clif_displaymessage(fd, atcmd_output); atcommand_memo_sub(sd); return -1; } @@ -3495,20 +3689,21 @@ int atcommand_gat( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char output[200]; int y; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); for (y = 2; y >= -2; y--) { - sprintf(output, "%s (x= %d, y= %d) %02X %02X %02X %02X %02X", - map[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y, - map_getcell(sd->bl.m, sd->bl.x - 2, sd->bl.y + y), - map_getcell(sd->bl.m, sd->bl.x - 1, sd->bl.y + y), - map_getcell(sd->bl.m, sd->bl.x, sd->bl.y + y), - map_getcell(sd->bl.m, sd->bl.x + 1, sd->bl.y + y), - map_getcell(sd->bl.m, sd->bl.x + 2, sd->bl.y + y)); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "%s (x= %d, y= %d) %02X %02X %02X %02X %02X", + map[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y, + map_getcell(sd->bl.m, sd->bl.x - 2, sd->bl.y + y, CELL_GETTYPE), + map_getcell(sd->bl.m, sd->bl.x - 1, sd->bl.y + y, CELL_GETTYPE), + map_getcell(sd->bl.m, sd->bl.x, sd->bl.y + y, CELL_GETTYPE), + map_getcell(sd->bl.m, sd->bl.x + 1, sd->bl.y + y, CELL_GETTYPE), + map_getcell(sd->bl.m, sd->bl.x + 2, sd->bl.y + y, CELL_GETTYPE)); + + clif_displaymessage(fd, atcmd_output); } return 0; @@ -3523,6 +3718,7 @@ int atcommand_packet( const char* command, const char* message) { int x = 0, y = 0; + nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d %d", &x, &y) < 2) { clif_displaymessage(fd, "Please, enter a status type/flag (usage: @packet <status type> <flag>)."); @@ -3579,6 +3775,7 @@ int atcommand_skillpoint( const char* command, const char* message) { int point, new_skill_point; + nullpo_retr(-1, sd); if (!message || !*message || (point = atoi(message)) == 0) { clif_displaymessage(fd, "Please, enter a number (usage: @skpoint <number of points>)."); @@ -3615,6 +3812,7 @@ int atcommand_zeny( const char* command, const char* message) { int zeny, new_zeny; + nullpo_retr(-1, sd); if (!message || !*message || (zeny = atoi(message)) == 0) { clif_displaymessage(fd, "Please, enter an amount (usage: @zeny <amount>)."); @@ -3656,13 +3854,13 @@ int atcommand_param( &sd->status.str, &sd->status.agi, &sd->status.vit, &sd->status.int_, &sd->status.dex, &sd->status.luk }; - char output[200]; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) { - sprintf(output, "Please, enter a valid value (usage: @str,@agi,@vit,@int,@dex,@luk <+/-adjustement>)."); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Please, enter a valid value (usage: @str,@agi,@vit,@int,@dex,@luk <+/-adjustement>)."); + clif_displaymessage(fd, atcmd_output); return -1; } @@ -3674,22 +3872,22 @@ int atcommand_param( } } if (index < 0 || index > MAX_STATUS_TYPE) { // normaly impossible... - sprintf(output, "Please, enter a valid value (usage: @str,@agi,@vit,@int,@dex,@luk <+/-adjustement>)."); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Please, enter a valid value (usage: @str,@agi,@vit,@int,@dex,@luk <+/-adjustement>)."); + clif_displaymessage(fd, atcmd_output); return -1; } new_value = (int)*status[index] + value; - if (value > 0 && (value > battle_config.max_parameter || new_value > battle_config.max_parameter)) // fix positiv overflow + if (value > 0 && ((unsigned int)value > battle_config.max_parameter || (unsigned int)new_value > battle_config.max_parameter)) // fix positiv overflow new_value = battle_config.max_parameter; - else if (value < 0 && (value < -battle_config.max_parameter || new_value < 1)) // fix negativ overflow + else if (value < 0 && (value < -(int)battle_config.max_parameter || new_value < 1)) // fix negativ overflow new_value = 1; if (new_value != (int)*status[index]) { *status[index] = new_value; clif_updatestatus(sd, SP_STR + index); clif_updatestatus(sd, SP_USTR + index); - pc_calcstatus(sd, 0); + status_calc_pc(sd, 0); clif_displaymessage(fd, msg_table[42]); // Stat changed. } else { if (value < 0) @@ -3716,6 +3914,7 @@ int atcommand_stat_all( &sd->status.str, &sd->status.agi, &sd->status.vit, &sd->status.int_, &sd->status.dex, &sd->status.luk }; + nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) value = battle_config.max_parameter; @@ -3724,16 +3923,16 @@ int atcommand_stat_all( for (index = 0; index < (int)(sizeof(status) / sizeof(status[0])); index++) { new_value = (int)*status[index] + value; - if (value > 0 && (value > battle_config.max_parameter || new_value > battle_config.max_parameter)) // fix positiv overflow + if (value > 0 && ((unsigned int)value > battle_config.max_parameter || (unsigned int)new_value > battle_config.max_parameter)) // fix positiv overflow new_value = battle_config.max_parameter; - else if (value < 0 && (value < -battle_config.max_parameter || new_value < 1)) // fix negativ overflow + else if (value < 0 && (value < -(int)battle_config.max_parameter || new_value < 1)) // fix negativ overflow new_value = 1; if (new_value != (int)*status[index]) { *status[index] = new_value; clif_updatestatus(sd, SP_STR + index); clif_updatestatus(sd, SP_USTR + index); - pc_calcstatus(sd, 0); + status_calc_pc(sd, 0); count++; } } @@ -3762,6 +3961,7 @@ int atcommand_guildlevelup( int level = 0; short added_level; struct guild *guild_info; + nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d", &level) < 1 || level == 0) { clif_displaymessage(fd, "Please, enter a valid level (usage: @guildlvup/@guildlvlup <# of levels>)."); @@ -3804,6 +4004,7 @@ int atcommand_makeegg( { struct item_data *item_data; int id, pet_id; + nullpo_retr(-1, sd); if (!message || !*message) { clif_displaymessage(fd, "Please, enter a monter/egg name/id (usage: @makeegg <pet_id>)."); @@ -3819,11 +4020,11 @@ int atcommand_makeegg( if (pet_id < 0) pet_id = search_petDB_index(id, PET_EGG); if (pet_id >= 0) { - sd->catch_target_class = pet_db[pet_id].class; + sd->catch_target_class = pet_db[pet_id].class_; intif_create_pet( sd->status.account_id, sd->status.char_id, - pet_db[pet_id].class, mob_db[pet_db[pet_id].class].lv, - pet_db[pet_id].EggID, 0, pet_db[pet_id].intimate, + (short)pet_db[pet_id].class_, (short)mob_db[pet_db[pet_id].class_].lv, + (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate, 100, 0, 1, pet_db[pet_id].jname); } else { clif_displaymessage(fd, msg_table[180]); // The monter/egg name/id doesn't exist. @@ -3841,6 +4042,7 @@ int atcommand_hatch( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); if (sd->status.pet_id <= 0) clif_sendegg(sd); else { @@ -3861,6 +4063,7 @@ int atcommand_petfriendly( { int friendly; int t; + nullpo_retr(-1, sd); if (!message || !*message || (friendly = atoi(message)) < 0) { clif_displaymessage(fd, "Please, enter a valid value (usage: @petfriendly <0-1000>)."); @@ -3877,9 +4080,9 @@ int atcommand_petfriendly( if ((sd->pet.intimate > 0 && t <= 0) || (sd->pet.intimate <= 0 && t > 0)) { if (sd->bl.prev != NULL) - pc_calcstatus(sd, 0); + status_calc_pc(sd, 0); else - pc_calcstatus(sd, 2); + status_calc_pc(sd, 2); } } clif_displaymessage(fd, msg_table[182]); // Pet friendly value changed! @@ -3908,6 +4111,7 @@ int atcommand_pethungry( const char* command, const char* message) { int hungry; + nullpo_retr(-1, sd); if (!message || !*message || (hungry = atoi(message)) < 0) { clif_displaymessage(fd, "Please, enter a valid number (usage: @pethungry <0-100>)."); @@ -3944,6 +4148,7 @@ int atcommand_petrename( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); if (sd->status.pet_id > 0 && sd->pd) { if (sd->pet.rename_flag != 0) { sd->pet.rename_flag = 0; @@ -3971,24 +4176,22 @@ atcommand_recall( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; - char output[200]; struct map_session_data *pl_sd = NULL; - + nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @recall <char name>)."); return -1; } - - memset(character, '\0', sizeof character); - if(sscanf(message, "%99[^\n]", character) < 1) + + memset(atcmd_player_name, '\0', sizeof atcmd_player_name); + if(sscanf(message, "%99[^\n]", atcmd_player_name) < 1) return -1; - if(strncmp(sd->status.name,character,24)==0) + if(strncmp(sd->status.name,atcmd_player_name,24)==0) return -1; - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can recall only lower or same level if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, "You are not authorised to warp somenone to your actual map."); @@ -3999,8 +4202,8 @@ atcommand_recall( return -1; } pc_setpos(pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2); - sprintf(output, msg_table[46], character); // %s recalled! - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[46], atcmd_player_name); // %s recalled! + clif_displaymessage(fd, atcmd_output); } else { clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. return -1; @@ -4021,23 +4224,23 @@ int atcommand_revive( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; struct map_session_data *pl_sd; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @revive <char name>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { - if (pc_isdead(sd)) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { + if (pc_isdead(pl_sd)) { pl_sd->status.hp = pl_sd->status.max_hp; clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); pc_setstand(pl_sd); if (battle_config.pc_invincible_time > 0) - pc_setinvincibletimer(sd, battle_config.pc_invincible_time); + pc_setinvincibletimer(pl_sd, battle_config.pc_invincible_time); clif_updatestatus(pl_sd, SP_HP); clif_updatestatus(pl_sd, SP_SP); clif_resurrection(&pl_sd->bl, 1); @@ -4061,24 +4264,24 @@ int atcommand_char_change_sex( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @charchangesex <name>)."); return -1; } // check player name - if (strlen(character) < 4) { + if (strlen(atcmd_player_name) < 4) { clif_displaymessage(fd, msg_table[86]); // Sorry, but a player name have at least 4 characters. return -1; - } else if (strlen(character) > 23) { + } else if (strlen(atcmd_player_name) > 23) { clif_displaymessage(fd, msg_table[87]); // Sorry, but a player name have 23 characters maximum. return -1; } else { - chrif_char_ask_name(sd->status.account_id, character, 5, 0, 0, 0, 0, 0, 0); // type: 5 - changesex + chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 5, 0, 0, 0, 0, 0, 0); // type: 5 - changesex clif_displaymessage(fd, msg_table[88]); // Character name sends to char-server to ask it. } @@ -4094,24 +4297,24 @@ int atcommand_char_block( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @charblock/@block <name>)."); return -1; } // check player name - if (strlen(character) < 4) { + if (strlen(atcmd_player_name) < 4) { clif_displaymessage(fd, msg_table[86]); // Sorry, but a player name have at least 4 characters. return -1; - } else if (strlen(character) > 23) { + } else if (strlen(atcmd_player_name) > 23) { clif_displaymessage(fd, msg_table[87]); // Sorry, but a player name have 23 characters maximum. return -1; } else { - chrif_char_ask_name(sd->status.account_id, character, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block + chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block clif_displaymessage(fd, msg_table[88]); // Character name sends to char-server to ask it. } @@ -4138,22 +4341,21 @@ int atcommand_char_ban( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char modif[100], character[100]; char * modif_p; int year, month, day, hour, minute, second, value; + nullpo_retr(-1, sd); - memset(modif, '\0', sizeof(modif)); - memset(character, '\0', sizeof(character)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%s %99[^\n]", modif, character) < 2) { + if (!message || !*message || sscanf(message, "%s %99[^\n]", atcmd_output, atcmd_player_name) < 2) { clif_displaymessage(fd, "Please, enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <name>)."); return -1; } - modif[sizeof(modif)-1] = '\0'; - character[sizeof(character)-1] = '\0'; + atcmd_output[sizeof(atcmd_output)-1] = '\0'; - modif_p = modif; + modif_p = atcmd_output; year = month = day = hour = minute = second = 0; while (modif_p[0] != '\0') { value = atoi(modif_p); @@ -4193,14 +4395,14 @@ int atcommand_char_ban( } // check player name - if (strlen(character) < 4) { + if (strlen(atcmd_player_name) < 4) { clif_displaymessage(fd, msg_table[86]); // Sorry, but a player name have at least 4 characters. return -1; - } else if (strlen(character) > 23) { + } else if (strlen(atcmd_player_name) > 23) { clif_displaymessage(fd, msg_table[87]); // Sorry, but a player name have 23 characters maximum. return -1; } else { - chrif_char_ask_name(sd->status.account_id, character, 2, year, month, day, hour, minute, second); // type: 2 - ban + chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 2, year, month, day, hour, minute, second); // type: 2 - ban clif_displaymessage(fd, msg_table[88]); // Character name sends to char-server to ask it. } @@ -4215,25 +4417,25 @@ int atcommand_char_unblock( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @charunblock <player_name>)."); return -1; } // check player name - if (strlen(character) < 4) { + if (strlen(atcmd_player_name) < 4) { clif_displaymessage(fd, msg_table[86]); // Sorry, but a player name have at least 4 characters. return -1; - } else if (strlen(character) > 23) { + } else if (strlen(atcmd_player_name) > 23) { clif_displaymessage(fd, msg_table[87]); // Sorry, but a player name have 23 characters maximum. return -1; } else { // send answer to login server via char-server - chrif_char_ask_name(sd->status.account_id, character, 3, 0, 0, 0, 0, 0, 0); // type: 3 - unblock + chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 3, 0, 0, 0, 0, 0, 0); // type: 3 - unblock clif_displaymessage(fd, msg_table[88]); // Character name sends to char-server to ask it. } @@ -4248,25 +4450,25 @@ int atcommand_char_unban( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @charunban <player_name>)."); return -1; } // check player name - if (strlen(character) < 4) { + if (strlen(atcmd_player_name) < 4) { clif_displaymessage(fd, msg_table[86]); // Sorry, but a player name have at least 4 characters. return -1; - } else if (strlen(character) > 23) { + } else if (strlen(atcmd_player_name) > 23) { clif_displaymessage(fd, msg_table[87]); // Sorry, but a player name have 23 characters maximum. return -1; } else { // send answer to login server via char-server - chrif_char_ask_name(sd->status.account_id, character, 4, 0, 0, 0, 0, 0, 0); // type: 4 - unban + chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 4, 0, 0, 0, 0, 0, 0); // type: 4 - unban clif_displaymessage(fd, msg_table[88]); // Character name sends to char-server to ask it. } @@ -4283,11 +4485,12 @@ int atcommand_night( { struct map_session_data *pl_sd; int i; + nullpo_retr(-1, sd); if (night_flag != 1) { night_flag = 1; // 0=day, 1=night [Yor] for(i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && !map[sd->bl.m].flag.indoors) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && !map[sd->bl.m].flag.indoors) { //pl_sd->opt2 |= STATE_BLIND; //clif_changeoption(&pl_sd->bl); if (battle_config.night_darkness_level > 0) @@ -4318,13 +4521,18 @@ int atcommand_day( { struct map_session_data *pl_sd; int i; + nullpo_retr(-1, sd); if (night_flag != 0) { night_flag = 0; // 0=day, 1=night [Yor] for(i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { - pl_sd->opt2 &= ~STATE_BLIND; - clif_changeoption(&pl_sd->bl); + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { + if (battle_config.night_darkness_level > 0) + clif_refresh (pl_sd); + else { + pl_sd->opt2 &= ~STATE_BLIND; + clif_changeoption(&pl_sd->bl); + } clif_displaymessage(pl_sd->fd, msg_table[60]); // Day has arrived. } } @@ -4346,9 +4554,10 @@ int atcommand_doom( { struct map_session_data *pl_sd; int i; + nullpo_retr(-1, sd); clif_specialeffect(&sd->bl,450,2); for(i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && i != fd && + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && i != fd && pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can doom only lower or same gm level pc_damage(NULL, pl_sd, pl_sd->status.hp + 1); clif_displaymessage(pl_sd->fd, msg_table[61]); // The holy messenger has given judgement. @@ -4369,9 +4578,10 @@ int atcommand_doommap( { struct map_session_data *pl_sd; int i; + nullpo_retr(-1, sd); clif_specialeffect(&sd->bl,450,3); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && i != fd && sd->bl.m == pl_sd->bl.m && + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && i != fd && sd->bl.m == pl_sd->bl.m && pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can doom only lower or same gm level pc_damage(NULL, pl_sd, pl_sd->status.hp + 1); // clif_specialeffect(&pl_sd->bl,450,1); @@ -4412,10 +4622,11 @@ int atcommand_raise( const char* command, const char* message) { int i; + nullpo_retr(-1, sd); for (i = 0; i < fd_max; i++) { if (session[i]) - atcommand_raise_sub(session[i]->session_data); + atcommand_raise_sub((struct map_session_data *) session[i]->session_data); } clif_displaymessage(fd, msg_table[64]); // Mercy has been granted. @@ -4433,8 +4644,10 @@ int atcommand_raisemap( struct map_session_data *pl_sd; int i; + nullpo_retr(-1, sd); + for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && sd->bl.m == pl_sd->bl.m) + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && sd->bl.m == pl_sd->bl.m) atcommand_raise_sub(pl_sd); } clif_displaymessage(fd, msg_table[64]); // Mercy has been granted. @@ -4451,17 +4664,17 @@ int atcommand_character_baselevel( const char* command, const char* message) { struct map_session_data *pl_sd; - char character[100]; int level = 0, i; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%d %99[^\n]", &level, character) < 2 || level == 0) { + if (!message || !*message || sscanf(message, "%d %99[^\n]", &level, atcmd_player_name) < 2 || level == 0) { clif_displaymessage(fd, "Please, enter a level adjustement and a player name (usage: @charbaselvl <#> <nickname>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can change base level only lower or same gm level if (level > 0) { @@ -4469,7 +4682,7 @@ int atcommand_character_baselevel( clif_displaymessage(fd, msg_table[91]); // Character's base level can't go any higher. return 0; } // End Addition - if (level > battle_config.maximum_level || level > (battle_config.maximum_level - pl_sd->status.base_level)) // fix positiv overflow + if ((unsigned int)level > battle_config.maximum_level || (unsigned int)level > (battle_config.maximum_level - pl_sd->status.base_level)) // fix positiv overflow level = battle_config.maximum_level - pl_sd->status.base_level; for (i = 1; i <= level; i++) pl_sd->status.status_point += (pl_sd->status.base_level + i + 14) / 5; @@ -4477,7 +4690,7 @@ int atcommand_character_baselevel( clif_updatestatus(pl_sd, SP_BASELEVEL); clif_updatestatus(pl_sd, SP_NEXTBASEEXP); clif_updatestatus(pl_sd, SP_STATUSPOINT); - pc_calcstatus(pl_sd, 0); + status_calc_pc(pl_sd, 0); pc_heal(pl_sd, pl_sd->status.max_hp, pl_sd->status.max_sp); clif_misceffect(&pl_sd->bl, 0); clif_displaymessage(fd, msg_table[65]); // Character's base level raised. @@ -4486,7 +4699,7 @@ int atcommand_character_baselevel( clif_displaymessage(fd, msg_table[193]); // Character's base level can't go any lower. return -1; } - if (level < -battle_config.maximum_level || level < (1 - pl_sd->status.base_level)) // fix negativ overflow + if (level < -(int)battle_config.maximum_level || level < (1 - (int)pl_sd->status.base_level)) // fix negativ overflow level = 1 - pl_sd->status.base_level; if (pl_sd->status.status_point > 0) { for (i = 0; i > level; i--) @@ -4498,7 +4711,7 @@ int atcommand_character_baselevel( pl_sd->status.base_level += level; clif_updatestatus(pl_sd, SP_BASELEVEL); clif_updatestatus(pl_sd, SP_NEXTBASEEXP); - pc_calcstatus(pl_sd, 0); + status_calc_pc(pl_sd, 0); clif_displaymessage(fd, msg_table[66]); // Character's base level lowered. } } else { @@ -4522,25 +4735,28 @@ int atcommand_character_joblevel( const char* command, const char* message) { struct map_session_data *pl_sd; - char character[100]; - int max_level = 50, level = 0; + unsigned int max_level = 50; + int level = 0; //“]¶‚â—{Žq‚Ìꇂ̌³‚ÌE‹Æ‚ðŽZo‚·‚é struct pc_base_job pl_s_class; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%d %99[^\n]", &level, character) < 2 || level == 0) { + if (!message || !*message || sscanf(message, "%d %99[^\n]", &level, atcmd_player_name) < 2 || level == 0) { clif_displaymessage(fd, "Please, enter a level adjustement and a player name (usage: @charjlvl <#> <nickname>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { - pl_s_class = pc_calc_base_job(pl_sd->status.class); + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { + pl_s_class = pc_calc_base_job(pl_sd->status.class_); if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can change job level only lower or same gm level if (pl_s_class.job == 0) max_level -= 40; - if ((pl_s_class.job == 23) || (pl_s_class.upper == 1 && pl_s_class.type == 2)) //ƒXƒpƒmƒr‚Æ“]¶E‚ÍJobƒŒƒxƒ‹‚ÌÅ‚‚ª70 - // To-do: super novices has max level 99 - celest + // super novices can go up to 99 [celest] + else if (pl_s_class.job == 23) + max_level += 49; + else if (pl_sd->status.class_ > 4007 && pl_sd->status.class_ < 4023) max_level += 20; if (level > 0) { @@ -4555,7 +4771,7 @@ int atcommand_character_joblevel( clif_updatestatus(pl_sd, SP_NEXTJOBEXP); pl_sd->status.skill_point += level; clif_updatestatus(pl_sd, SP_SKILLPOINT); - pc_calcstatus(pl_sd, 0); + status_calc_pc(pl_sd, 0); clif_misceffect(&pl_sd->bl, 1); clif_displaymessage(fd, msg_table[68]); // character's job level raised. } else { @@ -4574,7 +4790,7 @@ int atcommand_character_joblevel( pl_sd->status.skill_point = 0; clif_updatestatus(pl_sd, SP_SKILLPOINT); } // to add: remove status points from skills - pc_calcstatus(pl_sd, 0); + status_calc_pc(pl_sd, 0); clif_displaymessage(fd, msg_table[69]); // Character's job level lowered. } } else { @@ -4598,16 +4814,16 @@ int atcommand_kick( const char* command, const char* message) { struct map_session_data *pl_sd; - char character[100]; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @kick <charname>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) // you can kick only lower or same gm level clif_GM_kick(sd, pl_sd, 1); else { @@ -4632,9 +4848,10 @@ int atcommand_kickall( { struct map_session_data *pl_sd; int i; + nullpo_retr(-1, sd); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kick only lower or same gm level if (sd->status.account_id != pl_sd->status.account_id) clif_GM_kick(sd, pl_sd, 0); @@ -4654,6 +4871,7 @@ int atcommand_allskill( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); pc_allskillup(sd); // all skills sd->status.skill_point = 0; // 0 skill points clif_updatestatus(sd, SP_SKILLPOINT); // update @@ -4671,6 +4889,7 @@ int atcommand_questskill( const char* command, const char* message) { int skill_id; + nullpo_retr(-1, sd); if (!message || !*message || (skill_id = atoi(message)) < 0) { clif_displaymessage(fd, "Please, enter a quest skill number (usage: @questskill <#:0+>)."); @@ -4706,20 +4925,20 @@ int atcommand_charquestskill( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; struct map_session_data *pl_sd; int skill_id = 0; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%d %99[^\n]", &skill_id, character) < 2 || skill_id < 0) { + if (!message || !*message || sscanf(message, "%d %99[^\n]", &skill_id, atcmd_player_name) < 2 || skill_id < 0) { clif_displaymessage(fd, "Please, enter a quest skill number and a player name (usage: @charquestskill <#:0+> <char_name>)."); return -1; } if (skill_id >= 0 && skill_id < MAX_SKILL_DB) { if (skill_get_inf2(skill_id) & 0x01) { - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_checkskill(pl_sd, skill_id) == 0) { pc_skill(pl_sd, skill_id, 1, 0); clif_displaymessage(fd, msg_table[199]); // This player has learned the skill. @@ -4752,6 +4971,7 @@ int atcommand_lostskill( const char* command, const char* message) { int skill_id; + nullpo_retr(-1, sd); if (!message || !*message || (skill_id = atoi(message)) < 0) { clif_displaymessage(fd, "Please, enter a quest skill number (usage: @lostskill <#:0+>)."); @@ -4789,20 +5009,20 @@ int atcommand_charlostskill( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; struct map_session_data *pl_sd; int skill_id = 0; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%d %99[^\n]", &skill_id, character) < 2 || skill_id < 0) { + if (!message || !*message || sscanf(message, "%d %99[^\n]", &skill_id, atcmd_player_name) < 2 || skill_id < 0) { clif_displaymessage(fd, "Please, enter a quest skill number and a player name (usage: @charlostskill <#:0+> <char_name>)."); return -1; } if (skill_id >= 0 && skill_id < MAX_SKILL) { if (skill_get_inf2(skill_id) & 0x01) { - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_checkskill(pl_sd, skill_id) > 0) { pl_sd->status.skill[skill_id].lv = 0; pl_sd->status.skill[skill_id].flag = 0; @@ -4837,6 +5057,7 @@ int atcommand_spiritball( const char* command, const char* message) { int number; + nullpo_retr(-1, sd); if (!message || !*message || (number = atoi(message)) < 0) { clif_displaymessage(fd, "Please, enter a spirit ball number (usage: @spiritball <number: 0-1000>)."); @@ -4877,6 +5098,7 @@ int atcommand_party( const char* command, const char* message) { char party[100]; + nullpo_retr(-1, sd); memset(party, '\0', sizeof(party)); @@ -4885,7 +5107,7 @@ int atcommand_party( return -1; } - party_create(sd, party); + party_create(sd, party, 0, 0); return 0; } @@ -4900,6 +5122,7 @@ int atcommand_guild( { char guild[100]; int prev; + nullpo_retr(-1, sd); memset(guild, '\0', sizeof(guild)); @@ -4924,6 +5147,7 @@ int atcommand_agitstart( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); if (agit_flag == 1) { clif_displaymessage(fd, msg_table[73]); // Already it has started siege warfare. return -1; @@ -4944,6 +5168,7 @@ int atcommand_agitend( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); if (agit_flag == 0) { clif_displaymessage(fd, msg_table[75]); // Siege warfare hasn't started yet. return -1; @@ -4966,14 +5191,17 @@ int atcommand_mapexit( { struct map_session_data *pl_sd; int i; + nullpo_retr(-1, sd); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { if (sd->status.account_id != pl_sd->status.account_id) clif_GM_kick(sd, pl_sd, 0); } } clif_GM_kick(sd, sd, 0); + + flush_fifos(); runflag = 0; @@ -4989,30 +5217,30 @@ int atcommand_idsearch( const char* command, const char* message) { char item_name[100]; - char output[200]; - int i, match; + unsigned int i, match; struct item_data *item; + nullpo_retr(-1, sd); memset(item_name, '\0', sizeof(item_name)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%99s", item_name) < 0) { clif_displaymessage(fd, "Please, enter a part of item name (usage: @idsearch <part_of_item_name>)."); return -1; } - sprintf(output, msg_table[77], item_name); // The reference result of '%s' (name: id): - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[77], item_name); // The reference result of '%s' (name: id): + clif_displaymessage(fd, atcmd_output); match = 0; for(i = 0; i < 20000; i++) { if ((item = itemdb_exists(i)) != NULL && strstr(item->jname, item_name) != NULL) { match++; - sprintf(output, msg_table[78], item->jname, item->nameid); // %s: %d - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[78], item->jname, item->nameid); // %s: %d + clif_displaymessage(fd, atcmd_output); } } - sprintf(output, msg_table[79], match); // It is %d affair above. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[79], match); // It is %d affair above. + clif_displaymessage(fd, atcmd_output); return 0; } @@ -5025,23 +5253,22 @@ int atcommand_charskreset( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; - char output[200]; struct map_session_data *pl_sd; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); - memset(output, '\0', sizeof(output)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @charskreset <charname>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can reset skill points only lower or same gm level pc_resetskill(pl_sd); - sprintf(output, msg_table[206], character); // '%s' skill points reseted! - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[206], atcmd_player_name); // '%s' skill points reseted! + clif_displaymessage(fd, atcmd_output); } else { clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. return -1; @@ -5062,23 +5289,22 @@ int atcommand_charstreset( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; - char output[200]; struct map_session_data *pl_sd; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); - memset(output, '\0', sizeof(output)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @charstreset <charname>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can reset stats points only lower or same gm level pc_resetstate(pl_sd); - sprintf(output, msg_table[207], character); // '%s' stats points reseted! - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[207], atcmd_player_name); // '%s' stats points reseted! + clif_displaymessage(fd, atcmd_output); } else { clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. return -1; @@ -5101,27 +5327,26 @@ int atcommand_charmodel( { int hair_style = 0, hair_color = 0, cloth_color = 0; struct map_session_data *pl_sd; - char character[100]; - char output[200]; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); - memset(output, '\0', sizeof(output)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d %d %d %99[^\n]", &hair_style, &hair_color, &cloth_color, character) < 4 || hair_style < 0 || hair_color < 0 || cloth_color < 0) { - sprintf(output, "Please, enter a valid model and a player name (usage: @charmodel <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d> <name>).", + if (!message || !*message || sscanf(message, "%d %d %d %99[^\n]", &hair_style, &hair_color, &cloth_color, atcmd_player_name) < 4 || hair_style < 0 || hair_color < 0 || cloth_color < 0) { + sprintf(atcmd_output, "Please, enter a valid model and a player name (usage: @charmodel <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d> <name>).", MIN_HAIR_STYLE, MAX_HAIR_STYLE, MIN_HAIR_COLOR, MAX_HAIR_COLOR, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); - clif_displaymessage(fd, output); + clif_displaymessage(fd, atcmd_output); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE && hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR && cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) { if (cloth_color != 0 && pl_sd->status.sex == 1 && - (pl_sd->status.class == 12 || pl_sd->status.class == 17)) { + (pl_sd->status.class_ == 12 || pl_sd->status.class_ == 17)) { clif_displaymessage(fd, msg_table[35]); // You can't use this command with this class. return -1; } else { @@ -5151,18 +5376,18 @@ int atcommand_charskpoint( const char* command, const char* message) { struct map_session_data *pl_sd; - char character[100]; int new_skill_point; int point = 0; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%d %99[^\n]", &point, character) < 2 || point == 0) { + if (!message || !*message || sscanf(message, "%d %99[^\n]", &point, atcmd_player_name) < 2 || point == 0) { clif_displaymessage(fd, "Please, enter a number and a player name (usage: @charskpoint <amount> <name>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { new_skill_point = (int)pl_sd->status.skill_point + point; if (point > 0 && (point > 0x7FFF || new_skill_point > 0x7FFF)) // fix positiv overflow new_skill_point = 0x7FFF; @@ -5196,18 +5421,18 @@ int atcommand_charstpoint( const char* command, const char* message) { struct map_session_data *pl_sd; - char character[100]; int new_status_point; int point = 0; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%d %99[^\n]", &point, character) < 2 || point == 0) { + if (!message || !*message || sscanf(message, "%d %99[^\n]", &point, atcmd_player_name) < 2 || point == 0) { clif_displaymessage(fd, "Please, enter a number and a player name (usage: @charstpoint <amount> <name>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { new_status_point = (int)pl_sd->status.status_point + point; if (point > 0 && (point > 0x7FFF || new_status_point > 0x7FFF)) // fix positiv overflow new_status_point = 0x7FFF; @@ -5233,50 +5458,6 @@ int atcommand_charstpoint( } /*========================================== - * Character Zeny Point (Rewritten by [Yor]) - *------------------------------------------ - */ -int atcommand_charzeny( - const int fd, struct map_session_data* sd, - const char* command, const char* message) -{ - struct map_session_data *pl_sd; - char character[100]; - int zeny = 0, new_zeny; - - memset(character, '\0', sizeof(character)); - - if (!message || !*message || sscanf(message, "%d %99[^\n]", &zeny, character) < 2 || zeny == 0) { - clif_displaymessage(fd, "Please, enter a number and a player name (usage: @charzeny <zeny> <name>)."); - return -1; - } - - if ((pl_sd = map_nick2sd(character)) != NULL) { - new_zeny = pl_sd->status.zeny + zeny; - if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY)) // fix positiv overflow - new_zeny = MAX_ZENY; - else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0)) // fix negativ overflow - new_zeny = 0; - if (new_zeny != pl_sd->status.zeny) { - pl_sd->status.zeny = new_zeny; - clif_updatestatus(pl_sd, SP_ZENY); - clif_displaymessage(fd, msg_table[211]); // Character's number of zenys changed! - } else { - if (zeny < 0) - clif_displaymessage(fd, msg_table[41]); // Impossible to decrease the number/value. - else - clif_displaymessage(fd, msg_table[149]); // Impossible to increase the number/value. - return -1; - } - } else { - clif_displaymessage(fd, msg_table[3]); // Character not found. - return -1; - } - - return 0; -} - -/*========================================== * Recall All Characters Online To Your Location *------------------------------------------ */ @@ -5287,9 +5468,9 @@ int atcommand_recallall( struct map_session_data *pl_sd; int i; int count; - char output[200]; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, "You are not authorised to warp somenone to your actual map."); @@ -5298,7 +5479,7 @@ int atcommand_recallall( count = 0; for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && sd->status.account_id != pl_sd->status.account_id && + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && sd->status.account_id != pl_sd->status.account_id && pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can recall only lower or same level if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) count++; @@ -5309,8 +5490,8 @@ int atcommand_recallall( clif_displaymessage(fd, msg_table[92]); // All characters recalled! if (count) { - sprintf(output, "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", count); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", count); + clif_displaymessage(fd, atcmd_output); } return 0; @@ -5327,12 +5508,12 @@ int atcommand_guildrecall( struct map_session_data *pl_sd; int i; char guild_name[100]; - char output[200]; struct guild *g; int count; + nullpo_retr(-1, sd); memset(guild_name, '\0', sizeof(guild_name)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%99[^\n]", guild_name) < 1) { clif_displaymessage(fd, "Please, enter a guild name/id (usage: @guildrecall <guild_name/id>)."); @@ -5348,7 +5529,7 @@ int atcommand_guildrecall( (g = guild_search(atoi(message))) != NULL) { count = 0; for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && sd->status.account_id != pl_sd->status.account_id && pl_sd->status.guild_id == g->guild_id) { if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) @@ -5357,11 +5538,11 @@ int atcommand_guildrecall( pc_setpos(pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2); } } - sprintf(output, msg_table[93], g->name); // All online characters of the %s guild are near you. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[93], g->name); // All online characters of the %s guild are near you. + clif_displaymessage(fd, atcmd_output); if (count) { - sprintf(output, "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", count); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", count); + clif_displaymessage(fd, atcmd_output); } } else { clif_displaymessage(fd, msg_table[94]); // Incorrect name/ID, or no one from the guild is online. @@ -5382,12 +5563,12 @@ int atcommand_partyrecall( int i; struct map_session_data *pl_sd; char party_name[100]; - char output[200]; struct party *p; int count; + nullpo_retr(-1, sd); memset(party_name, '\0', sizeof(party_name)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%99[^\n]", party_name) < 1) { clif_displaymessage(fd, "Please, enter a party name/id (usage: @partyrecall <party_name/id>)."); @@ -5403,7 +5584,7 @@ int atcommand_partyrecall( (p = party_search(atoi(message))) != NULL) { count = 0; for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && sd->status.account_id != pl_sd->status.account_id && pl_sd->status.party_id == p->party_id) { if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) @@ -5412,11 +5593,11 @@ int atcommand_partyrecall( pc_setpos(pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2); } } - sprintf(output, msg_table[95], p->name); // All online characters of the %s party are near you. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[95], p->name); // All online characters of the %s party are near you. + clif_displaymessage(fd, atcmd_output); if (count) { - sprintf(output, "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", count); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", count); + clif_displaymessage(fd, atcmd_output); } } else { clif_displaymessage(fd, msg_table[96]); // Incorrect name or ID, or no one from the party is online. @@ -5434,6 +5615,7 @@ int atcommand_reloaditemdb( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); itemdb_reload(); clif_displaymessage(fd, msg_table[97]); // Item database reloaded. @@ -5448,7 +5630,9 @@ int atcommand_reloadmobdb( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); mob_reload(); + read_petdb(); clif_displaymessage(fd, msg_table[98]); // Monster database reloaded. return 0; @@ -5462,6 +5646,7 @@ int atcommand_reloadskilldb( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); skill_reload(); clif_displaymessage(fd, msg_table[99]); // Skill database reloaded. @@ -5469,28 +5654,92 @@ int atcommand_reloadskilldb( } /*========================================== + * @reloadatcommand + * atcommand_athena.conf ‚ÌƒŠƒ[ƒh + *------------------------------------------ + */ +int +atcommand_reloadatcommand( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + atcommand_config_read(ATCOMMAND_CONF_FILENAME); + clif_displaymessage(fd, msg_table[254]); + return 0; +} +/*========================================== + * @reloadbattleconf + * battle_athena.conf ‚ÌƒŠƒ[ƒh + *------------------------------------------ + */ +int +atcommand_reloadbattleconf( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + battle_config_read(BATTLE_CONF_FILENAME); + clif_displaymessage(fd, msg_table[255]); + return 0; +} +/*========================================== + * @reloadstatusdb + * job_db1.txt job_db2.txt job_db2-2.txt + * refine_db.txt size_fix.txt + * ‚ÌƒŠƒ[ƒh + *------------------------------------------ + */ +int +atcommand_reloadstatusdb( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + status_readdb(); + clif_displaymessage(fd, msg_table[256]); + return 0; +} +/*========================================== + * @reloadpcdb + * exp.txt skill_tree.txt attr_fix.txt + * ‚ÌƒŠƒ[ƒh + *------------------------------------------ + */ +int +atcommand_reloadpcdb( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + pc_readdb(); + clif_displaymessage(fd, msg_table[257]); + return 0; +} + +/*========================================== * *------------------------------------------ */ -#ifndef TXT_ONLY -int atcommand_rehash( -#else /* TXT_ONLY */ +void rehash(void) +{ + int map_id; + + for (map_id = 0; map_id < map_num; map_id++) { + map_foreachinarea(cleanup_sub, map_id, 0, 0, map[map_id].xs, map[map_id].ys, BL_MOB); + map_foreachinarea(cleanup_sub, map_id, 0, 0, map[map_id].xs, map[map_id].ys, BL_NPC); + } +} int atcommand_reloadscript( -#endif /* TXT_ONLY */ const int fd, struct map_session_data* sd, const char* command, const char* message) { -#ifndef TXT_ONLY - atcommand_broadcast( fd, sd, "@broadcast", "eAthena SQL Server is Rehashing..." ); + nullpo_retr(-1, sd); + atcommand_broadcast( fd, sd, "@broadcast", "eAthena Server is Rehashing..." ); atcommand_broadcast( fd, sd, "@broadcast", "You will feel a bit of lag at this point !" ); - - rehash( fd, sd ); + + rehash(); atcommand_broadcast( fd, sd, "@broadcast", "Reloading NPCs..." ); -#endif /* not TXT_ONLY */ - do_init_npc(); + //do_init_npc(); do_init_script(); - + npc_reload(); npc_event_do_oninit(); clif_displaymessage(fd, msg_table[100]); // Scripts reloaded. @@ -5506,6 +5755,7 @@ int atcommand_reloadgmdb( // by [Yor] const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); chrif_reloadGMdb(); clif_displaymessage(fd, msg_table[101]); // Login-server asked to reload GM accounts and their level. @@ -5529,71 +5779,71 @@ int atcommand_mapinfo( struct map_session_data *pl_sd; struct npc_data *nd = NULL; struct chat_data *cd = NULL; - char output[200], map_name[100]; char direction[12]; int m_id, i, chat_num, list = 0; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); - memset(map_name, '\0', sizeof(map_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); memset(direction, '\0', sizeof(direction)); - sscanf(message, "%d %99[^\n]", &list, map_name); + sscanf(message, "%d %99[^\n]", &list, atcmd_player_name); if (list < 0 || list > 3) { clif_displaymessage(fd, "Please, enter at least a valid list number (usage: @mapinfo <0-3> [map])."); return -1; } - if (map_name[0] == '\0') - strcpy(map_name, sd->mapname); - if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat) - strcat(map_name, ".gat"); + if (atcmd_player_name[0] == '\0') + strcpy(atcmd_player_name, sd->mapname); + if (strstr(atcmd_player_name, ".gat") == NULL && strstr(atcmd_player_name, ".afm") == NULL && strlen(atcmd_player_name) < 13) // 16 - 4 (.gat) + strcat(atcmd_player_name, ".gat"); - if ((m_id = map_mapname2mapid(map_name)) < 0) { + if ((m_id = map_mapname2mapid(atcmd_player_name)) < 0) { clif_displaymessage(fd, msg_table[1]); // Map not found. return -1; } clif_displaymessage(fd, "------ Map Info ------"); - sprintf(output, "Map Name: %s", map_name); - clif_displaymessage(fd, output); - sprintf(output, "Players In Map: %d", map[m_id].users); - clif_displaymessage(fd, output); - sprintf(output, "NPCs In Map: %d", map[m_id].npc_num); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Map Name: %s", atcmd_player_name); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, "Players In Map: %d", map[m_id].users); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, "NPCs In Map: %d", map[m_id].npc_num); + clif_displaymessage(fd, atcmd_output); chat_num = 0; for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && (cd = (struct chat_data*)map_id2bl(pl_sd->chatID))) { chat_num++; } } - sprintf(output, "Chats In Map: %d", chat_num); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "Chats In Map: %d", chat_num); + clif_displaymessage(fd, atcmd_output); clif_displaymessage(fd, "------ Map Flags ------"); - sprintf(output, "Player vs Player: %s | No Guild: %s | No Party: %s", + sprintf(atcmd_output, "Player vs Player: %s | No Guild: %s | No Party: %s", (map[m_id].flag.pvp) ? "True" : "False", (map[m_id].flag.pvp_noguild) ? "True" : "False", (map[m_id].flag.pvp_noparty) ? "True" : "False"); - clif_displaymessage(fd, output); - sprintf(output, "Guild vs Guild: %s | No Party: %s", (map[m_id].flag.gvg) ? "True" : "False", (map[m_id].flag.gvg_noparty) ? "True" : "False"); - clif_displaymessage(fd, output); - sprintf(output, "No Dead Branch: %s", (map[m_id].flag.nobranch) ? "True" : "False"); - clif_displaymessage(fd, output); - sprintf(output, "No Memo: %s", (map[m_id].flag.nomemo) ? "True" : "False"); - clif_displaymessage(fd, output); - sprintf(output, "No Penalty: %s", (map[m_id].flag.nopenalty) ? "True" : "False"); - clif_displaymessage(fd, output); - sprintf(output, "No Return: %s", (map[m_id].flag.noreturn) ? "True" : "False"); - clif_displaymessage(fd, output); - sprintf(output, "No Save: %s", (map[m_id].flag.nosave) ? "True" : "False"); - clif_displaymessage(fd, output); - sprintf(output, "No Teleport: %s", (map[m_id].flag.noteleport) ? "True" : "False"); - clif_displaymessage(fd, output); - sprintf(output, "No Monster Teleport: %s", (map[m_id].flag.monster_noteleport) ? "True" : "False"); - clif_displaymessage(fd, output); - sprintf(output, "No Zeny Penalty: %s", (map[m_id].flag.nozenypenalty) ? "True" : "False"); - clif_displaymessage(fd, output); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, "Guild vs Guild: %s | No Party: %s", (map[m_id].flag.gvg) ? "True" : "False", (map[m_id].flag.gvg_noparty) ? "True" : "False"); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, "No Dead Branch: %s", (map[m_id].flag.nobranch) ? "True" : "False"); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, "No Memo: %s", (map[m_id].flag.nomemo) ? "True" : "False"); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, "No Penalty: %s", (map[m_id].flag.nopenalty) ? "True" : "False"); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, "No Return: %s", (map[m_id].flag.noreturn) ? "True" : "False"); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, "No Save: %s", (map[m_id].flag.nosave) ? "True" : "False"); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, "No Teleport: %s", (map[m_id].flag.noteleport) ? "True" : "False"); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, "No Monster Teleport: %s", (map[m_id].flag.monster_noteleport) ? "True" : "False"); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, "No Zeny Penalty: %s", (map[m_id].flag.nozenypenalty) ? "True" : "False"); + clif_displaymessage(fd, atcmd_output); switch (list) { case 0: @@ -5602,10 +5852,10 @@ int atcommand_mapinfo( case 1: clif_displaymessage(fd, "----- Players in Map -----"); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && strcmp(pl_sd->mapname, map_name) == 0) { - sprintf(output, "Player '%s' (session #%d) | Location: %d,%d", + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && strcmp(pl_sd->mapname, atcmd_player_name) == 0) { + sprintf(atcmd_output, "Player '%s' (session #%d) | Location: %d,%d", pl_sd->status.name, i, pl_sd->bl.x, pl_sd->bl.y); - clif_displaymessage(fd, output); + clif_displaymessage(fd, atcmd_output); } } break; @@ -5625,24 +5875,24 @@ int atcommand_mapinfo( case 9: strcpy(direction, "North"); break; default: strcpy(direction, "Unknown"); break; } - sprintf(output, "NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d", - ++i, nd->name, direction, nd->class, nd->bl.x, nd->bl.y); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d", + ++i, nd->name, direction, nd->class_, nd->bl.x, nd->bl.y); + clif_displaymessage(fd, atcmd_output); } break; case 3: clif_displaymessage(fd, "----- Chats in Map -----"); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && (cd = (struct chat_data*)map_id2bl(pl_sd->chatID)) && - strcmp(pl_sd->mapname, map_name) == 0 && + strcmp(pl_sd->mapname, atcmd_player_name) == 0 && cd->usersd[0] == pl_sd) { - sprintf(output, "Chat %d: %s | Player: %s | Location: %d %d", + sprintf(atcmd_output, "Chat %d: %s | Player: %s | Location: %d %d", i, cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y); - clif_displaymessage(fd, output); - sprintf(output, " Users: %d/%d | Password: %s | Public: %s", + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, " Users: %d/%d | Password: %s | Public: %s", cd->users, cd->limit, cd->pass, (cd->pub) ? "Yes" : "No"); - clif_displaymessage(fd, output); + clif_displaymessage(fd, atcmd_output); } } break; @@ -5663,21 +5913,22 @@ int atcommand_mount_peco( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); if (sd->disguise > 0) { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris] clif_displaymessage(fd, msg_table[212]); // Cannot mount a Peco while in disguise. return -1; } if (!pc_isriding(sd)) { // if actually no peco - if (sd->status.class == 7 || sd->status.class == 14 || sd->status.class == 4008 || sd->status.class == 4015) { - if (sd->status.class == 7) - sd->status.class = sd->view_class = 13; - else if (sd->status.class == 14) - sd->status.class = sd->view_class = 21; - else if (sd->status.class == 4008) - sd->status.class = sd->view_class = 4014; - else if (sd->status.class == 4015) - sd->status.class = sd->view_class = 4022; + if (sd->status.class_ == 7 || sd->status.class_ == 14 || sd->status.class_ == 4008 || sd->status.class_ == 4015) { + if (sd->status.class_ == 7) + sd->status.class_ = sd->view_class = 13; + else if (sd->status.class_ == 14) + sd->status.class_ = sd->view_class = 21; + else if (sd->status.class_ == 4008) + sd->status.class_ = sd->view_class = 4014; + else if (sd->status.class_ == 4015) + sd->status.class_ = sd->view_class = 4022; pc_setoption(sd, sd->status.option | 0x0020); clif_displaymessage(fd, msg_table[102]); // Mounted Peco. } else { @@ -5685,14 +5936,14 @@ int atcommand_mount_peco( return -1; } } else { - if (sd->status.class == 13) - sd->status.class = sd->view_class = 7; - else if (sd->status.class == 21) - sd->status.class = sd->view_class = 14; - else if (sd->status.class == 4014) - sd->status.class = sd->view_class = 4008; - else if (sd->status.class == 4022) - sd->status.class = sd->view_class = 4015; + if (sd->status.class_ == 13) + sd->status.class_ = sd->view_class = 7; + else if (sd->status.class_ == 21) + sd->status.class_ = sd->view_class = 14; + else if (sd->status.class_ == 4014) + sd->status.class_ = sd->view_class = 4008; + else if (sd->status.class_ == 4022) + sd->status.class_ = sd->view_class = 4015; pc_setoption(sd, sd->status.option & ~0x0020); clif_displaymessage(fd, msg_table[214]); // Unmounted Peco. } @@ -5708,32 +5959,32 @@ int atcommand_char_mount_peco( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; struct map_session_data *pl_sd; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @charmountpeco <char_name>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pl_sd->disguise > 0) { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris] clif_displaymessage(fd, msg_table[215]); // This player cannot mount a Peco while in disguise. return -1; } if (!pc_isriding(pl_sd)) { // if actually no peco - if (pl_sd->status.class == 7 || pl_sd->status.class == 14 || pl_sd->status.class == 4008 || pl_sd->status.class == 4015) { - if (pl_sd->status.class == 7) - pl_sd->status.class = pl_sd->view_class = 13; - else if (pl_sd->status.class == 14) - pl_sd->status.class = pl_sd->view_class = 21; - else if (pl_sd->status.class == 4008) - pl_sd->status.class = pl_sd->view_class = 4014; - else if (pl_sd->status.class == 4015) - pl_sd->status.class = pl_sd->view_class = 4022; + if (pl_sd->status.class_ == 7 || pl_sd->status.class_ == 14 || pl_sd->status.class_ == 4008 || pl_sd->status.class_ == 4015) { + if (pl_sd->status.class_ == 7) + pl_sd->status.class_ = pl_sd->view_class = 13; + else if (pl_sd->status.class_ == 14) + pl_sd->status.class_ = pl_sd->view_class = 21; + else if (pl_sd->status.class_ == 4008) + pl_sd->status.class_ = pl_sd->view_class = 4014; + else if (pl_sd->status.class_ == 4015) + pl_sd->status.class_ = pl_sd->view_class = 4022; pc_setoption(pl_sd, pl_sd->status.option | 0x0020); clif_displaymessage(fd, msg_table[216]); // Now, this player mounts a peco. } else { @@ -5741,14 +5992,14 @@ int atcommand_char_mount_peco( return -1; } } else { - if (pl_sd->status.class == 13) - pl_sd->status.class = pl_sd->view_class = 7; - else if (pl_sd->status.class == 21) - pl_sd->status.class = pl_sd->view_class = 14; - else if (pl_sd->status.class == 4014) - pl_sd->status.class = pl_sd->view_class = 4008; - else if (pl_sd->status.class == 4022) - pl_sd->status.class = pl_sd->view_class = 4015; + if (pl_sd->status.class_ == 13) + pl_sd->status.class_ = pl_sd->view_class = 7; + else if (pl_sd->status.class_ == 21) + pl_sd->status.class_ = pl_sd->view_class = 14; + else if (pl_sd->status.class_ == 4014) + pl_sd->status.class_ = pl_sd->view_class = 4008; + else if (pl_sd->status.class_ == 4022) + pl_sd->status.class_ = pl_sd->view_class = 4015; pc_setoption(pl_sd, pl_sd->status.option & ~0x0020); clif_displaymessage(fd, msg_table[218]); // Now, this player has not more peco. } @@ -5769,11 +6020,11 @@ int atcommand_guildspy( const char* command, const char* message) { char guild_name[100]; - char output[200]; struct guild *g; + nullpo_retr(-1, sd); memset(guild_name, '\0', sizeof(guild_name)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%99[^\n]", guild_name) < 1) { clif_displaymessage(fd, "Please, enter a guild name/id (usage: @guildspy <guild_name/id>)."); @@ -5784,12 +6035,12 @@ int atcommand_guildspy( (g = guild_search(atoi(message))) != NULL) { if (sd->guildspy == g->guild_id) { sd->guildspy = 0; - sprintf(output, msg_table[103], g->name); // No longer spying on the %s guild. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[103], g->name); // No longer spying on the %s guild. + clif_displaymessage(fd, atcmd_output); } else { sd->guildspy = g->guild_id; - sprintf(output, msg_table[104], g->name); // Spying on the %s guild. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[104], g->name); // Spying on the %s guild. + clif_displaymessage(fd, atcmd_output); } } else { clif_displaymessage(fd, msg_table[94]); // Incorrect name/ID, or no one from the guild is online. @@ -5808,11 +6059,11 @@ int atcommand_partyspy( const char* command, const char* message) { char party_name[100]; - char output[200]; struct party *p; + nullpo_retr(-1, sd); memset(party_name, '\0', sizeof(party_name)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%99[^\n]", party_name) < 1) { clif_displaymessage(fd, "Please, enter a party name/id (usage: @partyspy <party_name/id>)."); @@ -5823,12 +6074,12 @@ int atcommand_partyspy( (p = party_search(atoi(message))) != NULL) { if (sd->partyspy == p->party_id) { sd->partyspy = 0; - sprintf(output, msg_table[105], p->name); // No longer spying on the %s party. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[105], p->name); // No longer spying on the %s party. + clif_displaymessage(fd, atcmd_output); } else { sd->partyspy = p->party_id; - sprintf(output, msg_table[106], p->name); // Spying on the %s party. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[106], p->name); // Spying on the %s party. + clif_displaymessage(fd, atcmd_output); } } else { clif_displaymessage(fd, msg_table[96]); // Incorrect name or ID, or no one from the party is online. @@ -5847,6 +6098,7 @@ int atcommand_repairall( const char* command, const char* message) { int count, i; + nullpo_retr(-1, sd); count = 0; for (i = 0; i < MAX_INVENTORY; i++) { @@ -5869,22 +6121,22 @@ int atcommand_repairall( return 0; } -/* Removed @nuke for now in favor of alchemist marine sphere skill [Valaris] +// Removed @nuke for now in favor of alchemist marine sphere skill [Valaris] int atcommand_nuke( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; struct map_session_data *pl_sd; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @nuke <char name>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kill only lower or same GM level skill_castend_damage_id(&pl_sd->bl, &pl_sd->bl, NPC_SELFDESTRUCTION, 99, gettick(), 0); clif_displaymessage(fd, msg_table[109]); // Player has been nuked! @@ -5899,7 +6151,7 @@ int atcommand_nuke( return 0; } -*/ + /*========================================== * @@ -5909,11 +6161,12 @@ int atcommand_enablenpc(const int fd, struct map_session_data* sd, const char* command, const char* message) { char NPCname[100]; + nullpo_retr(-1, sd); memset(NPCname, '\0', sizeof(NPCname)); if (!message || !*message || sscanf(message, "%99[^\n]", NPCname) < 1) { - clif_displaymessage(fd, "Please, enter a NPC name (usage: @npcon <NPC_name>)."); + clif_displaymessage(fd, "Please, enter a NPC name (usage: @enablenpc <NPC_name>)."); return -1; } @@ -5932,10 +6185,11 @@ int atcommand_enablenpc(const int fd, struct map_session_data* sd, * *------------------------------------------ */ -int atcommand_disablenpc(const int fd, struct map_session_data* sd, +int atcommand_hidenpc(const int fd, struct map_session_data* sd, const char* command, const char* message) { char NPCname[100]; + nullpo_retr(-1, sd); memset(NPCname, '\0', sizeof(NPCname)); @@ -5955,6 +6209,31 @@ int atcommand_disablenpc(const int fd, struct map_session_data* sd, return 0; } +int atcommand_disablenpc(const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct npc_data *nd; + char NPCname[100]; + nullpo_retr(-1, sd); + + memset(NPCname, '\0', sizeof(NPCname)); + + if (!message || !*message || sscanf(message, "%99[^\n]", NPCname) < 1) { + clif_displaymessage(fd, "Please, enter a NPC name (usage: @npcoff <NPC_name>)."); + return -1; + } + + if ((nd = npc_name2id(NPCname)) != NULL) { + npc_unload(nd); + clif_displaymessage(fd, msg_table[112]); // Npc Disabled. + } else { + clif_displaymessage(fd, msg_table[111]); // This NPC doesn't exist. + return -1; + } + + return 0; +} + /*========================================== * time in txt for time command (by [Yor]) *------------------------------------------ @@ -6010,6 +6289,7 @@ int atcommand_servertime(const int fd, struct map_session_data* sd, time_t time_server; // variable for number of seconds (used with time() function) struct tm *datetime; // variable for time in structure ->tm_mday, ->tm_sec, ... char temp[256]; + nullpo_retr(-1, sd); memset(temp, '\0', sizeof(temp)); @@ -6082,17 +6362,16 @@ int atcommand_chardelitem(const int fd, struct map_session_data* sd, const char* command, const char* message) { struct map_session_data *pl_sd; - char character[100]; char item_name[100]; int i, number = 0, item_id, item_position, count; - char output[200]; struct item_data *item_data; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); memset(item_name, '\0', sizeof(item_name)); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%s %d %99[^\n]", item_name, &number, character) < 3 || number < 1) { + if (!message || !*message || sscanf(message, "%s %d %99[^\n]", item_name, &number, atcmd_player_name) < 3 || number < 1) { clif_displaymessage(fd, "Please, enter an item name/id, a quantity and a player name (usage: @chardelitem <item_name_or_ID> <quantity> <player>)."); return -1; } @@ -6103,7 +6382,7 @@ int atcommand_chardelitem(const int fd, struct map_session_data* sd, item_id = item_data->nameid; if (item_id > 500) { - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kill only lower or same level item_position = pc_search_inventory(pl_sd, item_id); if (item_position >= 0) { @@ -6113,13 +6392,13 @@ int atcommand_chardelitem(const int fd, struct map_session_data* sd, count++; item_position = pc_search_inventory(pl_sd, item_id); // for next loop } - sprintf(output, msg_table[113], count); // %d item(s) removed by a GM. - clif_displaymessage(pl_sd->fd, output); + sprintf(atcmd_output, msg_table[113], count); // %d item(s) removed by a GM. + clif_displaymessage(pl_sd->fd, atcmd_output); if (number == count) - sprintf(output, msg_table[114], count); // %d item(s) removed from the player. + sprintf(atcmd_output, msg_table[114], count); // %d item(s) removed from the player. else - sprintf(output, msg_table[115], count, count, number); // %d item(s) removed. Player had only %d on %d items. - clif_displaymessage(fd, output); + sprintf(atcmd_output, msg_table[115], count, count, number); // %d item(s) removed. Player had only %d on %d items. + clif_displaymessage(fd, atcmd_output); } else { clif_displaymessage(fd, msg_table[116]); // Character does not have the item. return -1; @@ -6149,18 +6428,18 @@ int atcommand_jail( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; struct map_session_data *pl_sd; int x, y; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @jail <char_name>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can jail only lower or same GM switch(rand() % 2) { case 0: @@ -6201,23 +6480,22 @@ int atcommand_unjail( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; struct map_session_data *pl_sd; - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @unjail/@discharge <char_name>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can jail only lower or same GM if (pl_sd->bl.m != map_mapname2mapid("sec_pri.gat")) { clif_displaymessage(fd, msg_table[119]); // This player is not in jails. return -1; - } else if (pc_setpos(pl_sd, "prontera.gat", 156, 191, 3) == 0) { - pc_setsavepoint(pl_sd, "prontera.gat", 156, 191); // Save char respawn point in Prontera + } else if (pc_setpos(pl_sd, "prontera.gat", 0, 0, 3) == 0) { //old coords: 156,191 + pc_setsavepoint(pl_sd, "prontera.gat", 0, 0); // Save char respawn point in Prontera clif_displaymessage(pl_sd->fd, msg_table[120]); // GM has discharge you. clif_displaymessage(fd, msg_table[121]); // Player warped to Prontera. } else { @@ -6245,6 +6523,7 @@ int atcommand_disguise( const char* command, const char* message) { int mob_id = 0; + nullpo_retr(-1, sd); if (!message || !*message) { clif_displaymessage(fd, "Please, enter a Monster/NPC name/id (usage: @disguise <monster_name_or_monster_ID>)."); @@ -6257,7 +6536,7 @@ int atcommand_disguise( if ((mob_id >= 46 && mob_id <= 125) || (mob_id >= 700 && mob_id <= 718) || // NPC (mob_id >= 721 && mob_id <= 755) || (mob_id >= 757 && mob_id <= 811) || // NPC (mob_id >= 813 && mob_id <= 834) || // NPC - (mob_id > 1000 && mob_id < 1521)) { // monsters + (mob_id > 1000 && mob_id < 1582)) { // monsters if (pc_isriding(sd)) { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris] clif_displaymessage(fd, msg_table[227]); // Cannot wear disguise while riding a Peco. return -1; @@ -6275,6 +6554,50 @@ int atcommand_disguise( } /*========================================== + * DisguiseAll + *------------------------------------------ + */ + +int atcommand_disguiseall( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int mob_id=0, i=0; + struct map_session_data *pl_sd; + nullpo_retr(-1, sd); + + if (!message || !*message) { + clif_displaymessage(fd, "Please, enter a Monster/NPC name/id (usage: @disguiseall <monster_name_or_monster_ID>)."); + return -1; + } + + if ((mob_id = mobdb_searchname(message)) == 0) // check name first (to avoid possible name begining by a number) + mob_id = atoi(message); + + if ((mob_id >= 46 && mob_id <= 125) || (mob_id >= 700 && mob_id <= 718) || // NPC + (mob_id >= 721 && mob_id <= 755) || (mob_id >= 757 && mob_id <= 811) || // NPC + (mob_id >= 813 && mob_id <= 834) || // NPC + (mob_id > 1000 && mob_id < 1582)) { // monsters + for(i=0; i < fd_max; i++) { + if(session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { + if(pc_isriding(pl_sd)) { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris] + clif_displaymessage(fd, msg_table[227]); // Cannot wear disguise while riding a Peco. + } else { + pl_sd->disguiseflag = 1; // set to override items with disguise script [Valaris] + pl_sd->disguise = mob_id; + pc_setpos(pl_sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y, 3); + } + } + } + clif_displaymessage(fd, msg_table[122]); // Disguise applied. + } else { + return -1; + } + + return 0; +} + +/*========================================== * @undisguise by [Yor] *------------------------------------------ */ @@ -6282,6 +6605,7 @@ int atcommand_undisguise( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); if (sd->disguise) { clif_clearchar(&sd->bl, 9); sd->disguise = 0; @@ -6296,6 +6620,30 @@ int atcommand_undisguise( } /*========================================== + * UndisguiseAll + *------------------------------------------ + */ +int atcommand_undisguiseall( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct map_session_data *pl_sd; + int i; + nullpo_retr(-1, sd); + + for(i=0; i < fd_max; i++) { + if(session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && pl_sd->disguise) { + clif_clearchar(&pl_sd->bl, 9); + pl_sd->disguise = 0; + pc_setpos(pl_sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y, 3); + } + } + clif_displaymessage(fd, msg_table[124]); // Undisguise applied. + + return 0; +} + +/*========================================== * @broadcast by [Valaris] *------------------------------------------ */ @@ -6303,17 +6651,17 @@ int atcommand_broadcast( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char output[200]; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message) { clif_displaymessage(fd, "Please, enter a message (usage: @broadcast <message>)."); return -1; } - sprintf(output, "%s : %s", sd->status.name, message); - intif_GMmessage(output, strlen(output) + 1, 0); + sprintf(atcmd_output, "%s : %s", sd->status.name, message); + intif_GMmessage(atcmd_output, strlen(atcmd_output) + 1, 0); return 0; } @@ -6326,18 +6674,18 @@ int atcommand_localbroadcast( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char output[200]; + nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message) { clif_displaymessage(fd, "Please, enter a message (usage: @localbroadcast <message>)."); return -1; } - sprintf(output, "%s : %s", sd->status.name, message); + sprintf(atcmd_output, "%s : %s", sd->status.name, message); - clif_GMmessage(&sd->bl, output, strlen(output) + 1, 1); // 1: ALL_SAMEMAP + clif_GMmessage(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 1); // 1: ALL_SAMEMAP return 0; } @@ -6351,14 +6699,14 @@ int atcommand_chardisguise( const char* command, const char* message) { int mob_id; - char character[100]; char mob_name[100]; struct map_session_data* pl_sd; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); memset(mob_name, '\0', sizeof(mob_name)); - if (!message || !*message || sscanf(message, "%s %99[^\n]", mob_name, character) < 2) { + if (!message || !*message || sscanf(message, "%s %99[^\n]", mob_name, atcmd_player_name) < 2) { clif_displaymessage(fd, "Please, enter a Monster/NPC name/id and a player name (usage: @chardisguise <monster_name_or_monster_ID> <char name>)."); return -1; } @@ -6366,7 +6714,7 @@ int atcommand_chardisguise( if ((mob_id = mobdb_searchname(mob_name)) == 0) // check name first (to avoid possible name begining by a number) mob_id = atoi(mob_name); - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can disguise only lower or same level if ((mob_id >= 46 && mob_id <= 125) || (mob_id >= 700 && mob_id <= 718) || // NPC (mob_id >= 721 && mob_id <= 755) || (mob_id >= 757 && mob_id <= 811) || // NPC @@ -6404,17 +6752,17 @@ int atcommand_charundisguise( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; struct map_session_data* pl_sd; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @charundisguise <char name>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can undisguise only lower or same level if (pl_sd->disguise) { clif_clearchar(&pl_sd->bl, 9); @@ -6447,6 +6795,7 @@ int atcommand_email( { char actual_email[100]; char new_email[100]; + nullpo_retr(-1, sd); memset(actual_email, '\0', sizeof(actual_email)); memset(new_email, '\0', sizeof(new_email)); @@ -6486,6 +6835,7 @@ int atcommand_effect( { struct map_session_data *pl_sd; int type = 0, flag = 0, i; + nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d %d", &type,&flag) < 2) { clif_displaymessage(fd, "Please, enter at least a option (usage: @effect <type+>)."); @@ -6497,7 +6847,7 @@ int atcommand_effect( } else{ for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { clif_specialeffect(&pl_sd->bl, type, flag); clif_displaymessage(pl_sd->fd, msg_table[229]); // Your effect has changed. } @@ -6508,203 +6858,6 @@ int atcommand_effect( } /*========================================== - * @charitemlist <character>: Displays the list of a player's items. - *------------------------------------------ - */ -int -atcommand_character_item_list( - const int fd, struct map_session_data* sd, - const char* command, const char* message) -{ - struct map_session_data *pl_sd; - struct item_data *item_data, *item_temp; - int i, j, equip, count, counter, counter2; - char character[100], output[200], equipstr[100], outputtmp[200]; - - memset(character, '\0', sizeof(character)); - memset(output, '\0', sizeof(output)); - memset(equipstr, '\0', sizeof(equipstr)); - memset(outputtmp, '\0', sizeof(outputtmp)); - - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { - clif_displaymessage(fd, "Please, enter a player name (usage: @charitemlist <char name>)."); - return -1; - } - - if ((pl_sd = map_nick2sd(character)) != NULL) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can look items only lower or same level - counter = 0; - count = 0; - for (i = 0; i < MAX_INVENTORY; i++) { - if (pl_sd->status.inventory[i].nameid > 0 && (item_data = itemdb_search(pl_sd->status.inventory[i].nameid)) != NULL) { - counter = counter + pl_sd->status.inventory[i].amount; - count++; - if (count == 1) { - sprintf(output, "------ Items list of '%s' ------", pl_sd->status.name); - clif_displaymessage(fd, output); - } - if ((equip = pl_sd->status.inventory[i].equip)) { - strcpy(equipstr, "| equiped: "); - if (equip & 4) - strcat(equipstr, "robe/gargment, "); - if (equip & 8) - strcat(equipstr, "left accessory, "); - if (equip & 16) - strcat(equipstr, "body/armor, "); - if ((equip & 34) == 2) - strcat(equipstr, "right hand, "); - if ((equip & 34) == 32) - strcat(equipstr, "left hand, "); - if ((equip & 34) == 34) - strcat(equipstr, "both hands, "); - if (equip & 64) - strcat(equipstr, "feet, "); - if (equip & 128) - strcat(equipstr, "right accessory, "); - if ((equip & 769) == 1) - strcat(equipstr, "lower head, "); - if ((equip & 769) == 256) - strcat(equipstr, "top head, "); - if ((equip & 769) == 257) - strcat(equipstr, "lower/top head, "); - if ((equip & 769) == 512) - strcat(equipstr, "mid head, "); - if ((equip & 769) == 512) - strcat(equipstr, "lower/mid head, "); - if ((equip & 769) == 769) - strcat(equipstr, "lower/mid/top head, "); - // remove final ', ' - equipstr[strlen(equipstr) - 2] = '\0'; - } else - memset(equipstr, '\0', sizeof(equipstr)); - if (sd->status.inventory[i].refine) - sprintf(output, "%d %s %+d (%s %+d, id: %d) %s", pl_sd->status.inventory[i].amount, item_data->name, pl_sd->status.inventory[i].refine, item_data->jname, pl_sd->status.inventory[i].refine, pl_sd->status.inventory[i].nameid, equipstr); - else - sprintf(output, "%d %s (%s, id: %d) %s", pl_sd->status.inventory[i].amount, item_data->name, item_data->jname, pl_sd->status.inventory[i].nameid, equipstr); - clif_displaymessage(fd, output); - memset(output, '\0', sizeof(output)); - counter2 = 0; - for (j = 0; j < item_data->slot; j++) { - if (pl_sd->status.inventory[i].card[j]) { - if ((item_temp = itemdb_search(pl_sd->status.inventory[i].card[j])) != NULL) { - if (output[0] == '\0') - sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname); - else - sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname); - strcat(output, outputtmp); - } - } - } - if (output[0] != '\0') { - output[strlen(output) - 2] = ')'; - output[strlen(output) - 1] = '\0'; - clif_displaymessage(fd, output); - } - } - } - if (count == 0) - clif_displaymessage(fd, "No item found on this player."); - else { - sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count); - clif_displaymessage(fd, output); - } - } else { - clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. - return -1; - } - } else { - clif_displaymessage(fd, msg_table[3]); // Character not found. - return -1; - } - - return 0; -} - -/*========================================== - * @charstoragelist <character>: Displays the items list of a player's storage. - *------------------------------------------ - */ -int -atcommand_character_storage_list( - const int fd, struct map_session_data* sd, - const char* command, const char* message) -{ - struct storage *stor; - struct map_session_data *pl_sd; - struct item_data *item_data, *item_temp; - int i, j, count, counter, counter2; - char character[100], output[200], outputtmp[200]; - - memset(character, '\0', sizeof(character)); - memset(output, '\0', sizeof(output)); - memset(outputtmp, '\0', sizeof(outputtmp)); - - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { - clif_displaymessage(fd, "Please, enter a player name (usage: @charitemlist <char name>)."); - return -1; - } - - if ((pl_sd = map_nick2sd(character)) != NULL) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can look items only lower or same level - if((stor = account2storage2(pl_sd->status.account_id)) != NULL) { - counter = 0; - count = 0; - for (i = 0; i < MAX_STORAGE; i++) { - if (stor->storage[i].nameid > 0 && (item_data = itemdb_search(stor->storage[i].nameid)) != NULL) { - counter = counter + stor->storage[i].amount; - count++; - if (count == 1) { - sprintf(output, "------ Storage items list of '%s' ------", pl_sd->status.name); - clif_displaymessage(fd, output); - } - if (stor->storage[i].refine) - sprintf(output, "%d %s %+d (%s %+d, id: %d)", stor->storage[i].amount, item_data->name, stor->storage[i].refine, item_data->jname, stor->storage[i].refine, stor->storage[i].nameid); - else - sprintf(output, "%d %s (%s, id: %d)", stor->storage[i].amount, item_data->name, item_data->jname, stor->storage[i].nameid); - clif_displaymessage(fd, output); - memset(output, '\0', sizeof(output)); - counter2 = 0; - for (j = 0; j < item_data->slot; j++) { - if (stor->storage[i].card[j]) { - if ((item_temp = itemdb_search(stor->storage[i].card[j])) != NULL) { - if (output[0] == '\0') - sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname); - else - sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname); - strcat(output, outputtmp); - } - } - } - if (output[0] != '\0') { - output[strlen(output) - 2] = ')'; - output[strlen(output) - 1] = '\0'; - clif_displaymessage(fd, output); - } - } - } - if (count == 0) - clif_displaymessage(fd, "No item found in the storage of this player."); - else { - sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count); - clif_displaymessage(fd, output); - } - } else { - clif_displaymessage(fd, "This player has no storage."); - return 0; - } - } else { - clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. - return -1; - } - } else { - clif_displaymessage(fd, msg_table[3]); // Character not found. - return -1; - } - - return 0; -} - -/*========================================== * @charcartlist <character>: Displays the items list of a player's cart. *------------------------------------------ */ @@ -6713,21 +6866,22 @@ atcommand_character_cart_list( const int fd, struct map_session_data* sd, const char* command, const char* message) { + char outputtmp[200]; struct map_session_data *pl_sd; struct item_data *item_data, *item_temp; int i, j, count, counter, counter2; - char character[100], output[200], outputtmp[200]; + nullpo_retr(-1, sd); - memset(character, '\0', sizeof(character)); - memset(output, '\0', sizeof(output)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(outputtmp, '\0', sizeof(outputtmp)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { clif_displaymessage(fd, "Please, enter a player name (usage: @charitemlist <char name>)."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can look items only lower or same level counter = 0; count = 0; @@ -6736,39 +6890,39 @@ atcommand_character_cart_list( counter = counter + pl_sd->status.cart[i].amount; count++; if (count == 1) { - sprintf(output, "------ Cart items list of '%s' ------", pl_sd->status.name); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "------ Cart items list of '%s' ------", pl_sd->status.name); + clif_displaymessage(fd, atcmd_output); } if (pl_sd->status.cart[i].refine) - sprintf(output, "%d %s %+d (%s %+d, id: %d)", pl_sd->status.cart[i].amount, item_data->name, pl_sd->status.cart[i].refine, item_data->jname, pl_sd->status.cart[i].refine, pl_sd->status.cart[i].nameid); + sprintf(atcmd_output, "%d %s %+d (%s %+d, id: %d)", pl_sd->status.cart[i].amount, item_data->name, pl_sd->status.cart[i].refine, item_data->jname, pl_sd->status.cart[i].refine, pl_sd->status.cart[i].nameid); else - sprintf(output, "%d %s (%s, id: %d)", pl_sd->status.cart[i].amount, item_data->name, item_data->jname, pl_sd->status.cart[i].nameid); - clif_displaymessage(fd, output); - memset(output, '\0', sizeof(output)); + sprintf(atcmd_output, "%d %s (%s, id: %d)", pl_sd->status.cart[i].amount, item_data->name, item_data->jname, pl_sd->status.cart[i].nameid); + clif_displaymessage(fd, atcmd_output); + memset(atcmd_output, '\0', sizeof(atcmd_output)); counter2 = 0; for (j = 0; j < item_data->slot; j++) { if (pl_sd->status.cart[i].card[j]) { - if ((item_temp = itemdb_search(pl_sd->status.cart[i].card[j])) != NULL) { - if (output[0] == '\0') + if ( (item_temp = itemdb_search(pl_sd->status.cart[i].card[j])) != NULL) { + if (atcmd_output[0] == '\0') sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname); else sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname); - strcat(output, outputtmp); + strcat(atcmd_output, outputtmp); } } } - if (output[0] != '\0') { - output[strlen(output) - 2] = ')'; - output[strlen(output) - 1] = '\0'; - clif_displaymessage(fd, output); + if (atcmd_output[0] != '\0') { + atcmd_output[strlen(atcmd_output) - 2] = ')'; + atcmd_output[strlen(atcmd_output) - 1] = '\0'; + clif_displaymessage(fd, atcmd_output); } } } if (count == 0) clif_displaymessage(fd, "No item found in the cart of this player."); else { - sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "%d item(s) found in %d kind(s) of items.", counter, count); + clif_displaymessage(fd, atcmd_output); } } else { clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. @@ -6792,6 +6946,7 @@ atcommand_killer( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); sd->special_state.killer = !sd->special_state.killer; if(sd->special_state.killer) @@ -6812,6 +6967,7 @@ atcommand_killable( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); sd->special_state.killable = !sd->special_state.killable; if(sd->special_state.killable) @@ -6833,6 +6989,7 @@ atcommand_charkillable( const char* command, const char* message) { struct map_session_data *pl_sd = NULL; + nullpo_retr(-1, sd); if (!message || !*message) return -1; @@ -6861,6 +7018,7 @@ atcommand_skillon( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); map[sd->bl.m].flag.noskill = 0; clif_displaymessage(fd, msg_table[244]); return 0; @@ -6876,6 +7034,7 @@ atcommand_skilloff( const int fd, struct map_session_data* sd, const char* command, const char* message) { + nullpo_retr(-1, sd); map[sd->bl.m].flag.noskill = 1; clif_displaymessage(fd, msg_table[243]); return 0; @@ -6891,31 +7050,29 @@ int atcommand_npcmove(const int fd, struct map_session_data* sd, const char* command, const char* message) { - char character[100]; int x = 0, y = 0; struct npc_data *nd = 0; - - if( sd == NULL ) - return -1; + nullpo_retr(-1, sd); + if (!message || !*message) return -1; - memset(character, '\0', sizeof character); + memset(atcmd_player_name, '\0', sizeof atcmd_player_name); - if (sscanf(message, "%d %d %99[^\n]", &x, &y, character) < 4) + if (sscanf(message, "%d %d %99[^\n]", &x, &y, atcmd_player_name) < 3) { + clif_displaymessage(fd, "Usage: @npcmove <X> <Y> <npc_name>"); return -1; + } - nd=npc_name2id(character); - if (nd==NULL) - return -1; + nullpo_retr(-1, (nd = npc_name2id(atcmd_player_name))); - npc_enable(character, 0); - nd->bl.x = x; - nd->bl.y = y; - npc_enable(character, 1); + npc_enable(atcmd_player_name, 0); + nd->bl.x = x; + nd->bl.y = y; + npc_enable(atcmd_player_name, 1); - return 0; + return 0; } /*========================================== @@ -6929,24 +7086,24 @@ atcommand_addwarp(const int fd, struct map_session_data* sd, const char* command, const char* message) { char w1[64], w3[64], w4[64]; - char map[30], output[200]; int x,y,ret; + nullpo_retr(-1, sd); if (!message || !*message) return -1; - if (sscanf(message, "%99s %d %d[^\n]", map, &x, &y ) < 3) + if (sscanf(message, "%99s %d %d[^\n]", atcmd_player_name, &x, &y ) < 3) return -1; sprintf(w1,"%s,%d,%d", sd->mapname, sd->bl.x, sd->bl.y); - sprintf(w3,"%s%d%d%d%d", map,sd->bl.x, sd->bl.y, x, y); - sprintf(w4,"1,1,%s.gat,%d,%d", map, x, y); + sprintf(w3,"%s%d%d%d%d", atcmd_player_name,sd->bl.x, sd->bl.y, x, y); + sprintf(w4,"1,1,%s.gat,%d,%d", atcmd_player_name, x, y); ret = npc_parse_warp(w1, "warp", w3, w4); - sprintf(output, "New warp NPC => %s",w3); + sprintf(atcmd_output, "New warp NPC => %s",w3); - clif_displaymessage(fd, output); + clif_displaymessage(fd, atcmd_output); return ret; } @@ -6962,6 +7119,7 @@ atcommand_follow(const int fd, struct map_session_data* sd, const char* command, const char* message) { struct map_session_data *pl_sd = NULL; + nullpo_retr(-1, sd); if (!message || !*message) return -1; @@ -6974,33 +7132,6 @@ atcommand_follow(const int fd, struct map_session_data* sd, /*========================================== - * @chareffect by [MouseJstr] - * - * Create a effect localized on another character - *------------------------------------------ - */ -int -atcommand_chareffect(const int fd, struct map_session_data* sd, - const char* command, const char* message) -{ - struct map_session_data *pl_sd = NULL; - char target[255]; - int type = 0; - - if (!message || !*message || sscanf(message, "%d %s", &type, target) != 2) { - clif_displaymessage(fd, "usage: @chareffect <type+> <target>."); - return -1; - } - - if((pl_sd=map_nick2sd((char *) target)) == NULL) - return -1; - - clif_specialeffect(&pl_sd->bl, type, 0); - clif_displaymessage(fd, msg_table[229]); // Your effect has changed. - - return 0; -} -/*========================================== * @dropall by [MouseJstr] * * Drop all your possession on the ground @@ -7011,10 +7142,11 @@ atcommand_dropall(const int fd, struct map_session_data* sd, const char* command, const char* message) { int i; + nullpo_retr(-1, sd); for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].amount) { if(sd->status.inventory[i].equip != 0) - pc_unequipitem(sd, i, 0, BF_NORMAL); + pc_unequipitem(sd, i, 3); pc_dropitem(sd, i, sd->status.inventory[i].amount); } } @@ -7022,7 +7154,7 @@ atcommand_dropall(const int fd, struct map_session_data* sd, } /*========================================== * @chardropall by [MouseJstr] - * + * * Throw all the characters possessions on the ground. Normally * done in response to them being disrespectful of a GM *------------------------------------------ @@ -7033,6 +7165,7 @@ atcommand_chardropall(const int fd, struct map_session_data* sd, { int i; struct map_session_data *pl_sd = NULL; + nullpo_retr(-1, sd); if (!message || !*message) return -1; @@ -7041,7 +7174,7 @@ atcommand_chardropall(const int fd, struct map_session_data* sd, for (i = 0; i < MAX_INVENTORY; i++) { if (pl_sd->status.inventory[i].amount) { if(pl_sd->status.inventory[i].equip != 0) - pc_unequipitem(pl_sd, i, 0, BF_NORMAL); + pc_unequipitem(pl_sd, i, 3); pc_dropitem(pl_sd, i, pl_sd->status.inventory[i].amount); } } @@ -7064,6 +7197,7 @@ atcommand_storeall(const int fd, struct map_session_data* sd, const char* command, const char* message) { int i; + nullpo_retr(-1, sd); if (storage_storageopen(sd) == 1) { clif_displaymessage(fd, "run this command again.."); return 0; @@ -7071,7 +7205,7 @@ atcommand_storeall(const int fd, struct map_session_data* sd, for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].amount) { if(sd->status.inventory[i].equip != 0) - pc_unequipitem(sd, i, 0, BF_NORMAL); + pc_unequipitem(sd, i, 3); storage_storageadd(sd, i, sd->status.inventory[i].amount); } } @@ -7092,10 +7226,11 @@ atcommand_charstoreall(const int fd, struct map_session_data* sd, { int i; struct map_session_data *pl_sd = NULL; + nullpo_retr(-1, sd); if (!message || !*message) return -1; - if((pl_sd=map_nick2sd((char *) message)) == NULL) + if((pl_sd=map_nick2sd((char *) message)) == NULL) return -1; if (storage_storageopen(pl_sd) == 1) { @@ -7106,7 +7241,7 @@ atcommand_charstoreall(const int fd, struct map_session_data* sd, for (i = 0; i < MAX_INVENTORY; i++) { if (pl_sd->status.inventory[i].amount) { if(pl_sd->status.inventory[i].equip != 0) - pc_unequipitem(pl_sd, i, 0, BF_NORMAL); + pc_unequipitem(pl_sd, i, 3); storage_storageadd(pl_sd, i, sd->status.inventory[i].amount); } } @@ -7131,15 +7266,15 @@ atcommand_skillid(const int fd, struct map_session_data* sd, const char* command, const char* message) { int skillen = 0, idx = 0; + nullpo_retr(-1, sd); if (!message || !*message) return -1; skillen = strlen(message); while (skill_names[idx].id != 0) { if ((strnicmp(skill_names[idx].name, message, skillen) == 0) || (strnicmp(skill_names[idx].desc, message, skillen) == 0)) { - char output[255]; - sprintf(output, "skill %d: %s", skill_names[idx].id, skill_names[idx].desc); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "skill %d: %s", skill_names[idx].id, skill_names[idx].desc); + clif_displaymessage(fd, atcmd_output); } idx++; } @@ -7161,10 +7296,11 @@ atcommand_useskill(const int fd, struct map_session_data* sd, int skilllv; int inf; char target[255]; + nullpo_retr(-1, sd); if (!message || !*message) return -1; - if(sscanf(message, "%d %d %s", &skillnum, &skilllv, target) != 3) { + if(sscanf(message, "%d %d %99[^\n]", &skillnum, &skilllv, target) != 3) { clif_displaymessage(fd, "Usage: @useskill <skillnum> <skillv> <target>"); return -1; } @@ -7197,7 +7333,8 @@ atcommand_skilltree(const int fd, struct map_session_data* sd, int meets = 1, j, c=0, s=0; struct pc_base_job s_class; char target[255], *tbl; - char output[255]; + struct skill_tree_entry *ent; + nullpo_retr(-1, sd); if (!message || !*message) return -1; @@ -7206,10 +7343,10 @@ atcommand_skilltree(const int fd, struct map_session_data* sd, clif_displaymessage(fd, "Usage: @skilltree <skillnum> <target>"); return -1; } - if((pl_sd=map_nick2sd(target)) == NULL) + if((pl_sd=map_nick2sd(target)) == NULL) return -1; - s_class = pc_calc_base_job(pl_sd->status.class); + s_class = pc_calc_base_job(pl_sd->status.class_); c = s_class.job; s = s_class.upper; @@ -7217,52 +7354,295 @@ atcommand_skilltree(const int fd, struct map_session_data* sd, tbl = job_name(c); - sprintf(output, "Player is using %s %s skill tree (%d basic points)", - s_class.upper ? "upper" : "lower", + sprintf(atcmd_output, "Player is using %s %s skill tree (%d basic points)", + s_class.upper ? "upper" : "lower", tbl, pc_checkskill(pl_sd, 1)); - clif_displaymessage(fd, output); + clif_displaymessage(fd, atcmd_output); - for (j = 0; j < MAX_SKILL; j++) { + for (j = 0; skill_tree[s][c][j].id != 0; j++) { if (skill_tree[s][c][j].id == skillnum) { skillidx = j; break; } } - + if (skillidx == -1) { - sprintf(output, "I do not believe the player can use that skill"); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "I do not believe the player can use that skill"); + clif_displaymessage(fd, atcmd_output); return 0; } - struct skill_tree_entry *ent = &skill_tree[s][c][skillidx]; + ent = &skill_tree[s][c][skillidx]; - for(j=0;j<5;j++) + for(j=0;j<5;j++) if( ent->need[j].id && - pc_checkskill(sd,ent->need[j].id) < ent->need[j].lv) + pc_checkskill(sd,ent->need[j].id) < ent->need[j].lv) { int idx = 0; char *desc; - while (skill_names[idx].id != 0 && skill_names[idx].id != ent->need[j].id) + while (skill_names[idx].id != 0 && skill_names[idx].id != ent->need[j].id) idx++; if (skill_names[idx].id == 0) desc = "Unknown skill"; else desc = skill_names[idx].desc; - sprintf(output, "player requires level %d of skill %s", + sprintf(atcmd_output, "player requires level %d of skill %s", ent->need[j].lv, desc); - clif_displaymessage(fd, output); + clif_displaymessage(fd, atcmd_output); meets = 0; } if (meets == 1) { - sprintf(output, "I believe the player meets all the requirements for that skill"); - clif_displaymessage(fd, output); + sprintf(atcmd_output, "I believe the player meets all the requirements for that skill"); + clif_displaymessage(fd, atcmd_output); + } + + return 0; +} + +/*========================================== + * @marry by [MouseJstr], fixed by Lupus + * + * Marry two players + *------------------------------------------ + */ +int +atcommand_marry(const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct map_session_data *pl_sd1 = NULL; + struct map_session_data *pl_sd2 = NULL; + char player1[255], player2[255]; + + nullpo_retr(-1, sd); + + if (!message || !*message || sscanf(message, "%[^,],%[^\r\n]", player1, player2) != 2) { + clif_displaymessage(fd, "Usage: @marry <player1>,<player2>."); + return -1; + } + + if((pl_sd1=map_nick2sd((char *) player1)) == NULL) { + sprintf(player2, "Cannot find player '%s' online", player1); + clif_displaymessage(fd, player2); + return -1; + } + + if((pl_sd2=map_nick2sd((char *) player2)) == NULL) { + sprintf(player1, "Cannot find player '%s' online", player2); + clif_displaymessage(fd, player1); + return -1; + } + + if (pc_marriage(pl_sd1, pl_sd2) == 0) { + clif_displaymessage(fd, "They are married.. wish them well"); + clif_wedding_effect(&sd->bl); //wedding effect and music [Lupus] + return 0; + } + return -1; +} + +/*========================================== + * @divorce by [MouseJstr], fixed by [Lupus] + * + * divorce two players + *------------------------------------------ + */ +int +atcommand_divorce(const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct map_session_data *pl_sd = NULL; + + nullpo_retr(-1, sd); + + if (!message || !*message || sscanf(message, "%[^\r\n]", atcmd_player_name) != 1) { + clif_displaymessage(fd, "Usage: @divorce <player>."); + return -1; + } + + if((pl_sd=map_nick2sd((char *) atcmd_player_name)) != NULL) { + if (pc_divorce(pl_sd) != 0) { + sprintf(atcmd_output, "The divorce has failed.. Cannot find player '%s' or his(her) partner online.", atcmd_player_name); + clif_displaymessage(fd, atcmd_output); + return -1; + } else { + sprintf(atcmd_output, "'%s' and his(her) partner are now divorced.", atcmd_player_name); + clif_displaymessage(fd, atcmd_output); + return 0; + } } - + sprintf(atcmd_output, "Cannot find player '%s' online", atcmd_player_name); + clif_displaymessage(fd, atcmd_output); + return -1; +} + +/*========================================== + * @rings by [MouseJstr] + * + * Give two players rings + *------------------------------------------ + */ +int +atcommand_rings(const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct item item_tmp; + int flag; + + memset(&item_tmp, 0, sizeof(item_tmp)); + + item_tmp.nameid = 2634; + item_tmp.identify = 1; + + if ((flag = pc_additem((struct map_session_data*)sd, &item_tmp, 1))) + clif_additem((struct map_session_data*)sd, 0, 0, flag); + + item_tmp.nameid = 2635; + item_tmp.identify = 1; + if ((flag = pc_additem((struct map_session_data*)sd, &item_tmp, 1))) + clif_additem((struct map_session_data*)sd, 0, 0, flag); + + clif_displaymessage(fd, "You have rings! Give them to the lovers."); + + return 0; +} + +#ifdef DMALLOC +unsigned long dmark_; +int +atcommand_dmstart(const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + dmark_ = dmalloc_mark(); + + clif_displaymessage(fd, "debug mark set"); + return 0; } +int +atcommand_dmtick(const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + dmalloc_log_changed ( dmark_, 1, 0, 1 ) ; + dmark_ = dmalloc_mark(); + clif_displaymessage(fd, "malloc changes logged"); + + return 0; +} +#endif + +/*========================================== + * @grind by [MouseJstr] + *------------------------------------------ + */ +int +atcommand_grind(const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct map_session_data *pl_sd = NULL; + int skillnum; + int inf; + char target[255]; + nullpo_retr(-1, sd); + + if (!message || !*message) + return -1; + if(sscanf(message, "%s", target) != 1) { + clif_displaymessage(fd, "Usage: @grind <target>"); + return -1; + } + if((pl_sd=map_nick2sd(target)) == NULL) + return -1; + + for (skillnum = 1; skillnum < 500; skillnum++) { + sd->status.sp = sd->status.max_sp; + atcommand_alive(fd, sd, command, message); + + inf = skill_get_inf(skillnum); + + if ((inf == 2) || (inf == 1)) + skill_use_pos(sd, pl_sd->bl.x+5, pl_sd->bl.y+5, skillnum, 1); + else + skill_use_id(sd, pl_sd->bl.id, skillnum, 1); + } + + return 0; +} + +/*========================================== + * @grind2 by [MouseJstr] + *------------------------------------------ + */ +int +atcommand_grind2(const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int i, x, y, id; + + for (i = 1000; i <2000; i++) { + x = sd->bl.x + (rand() % 10 - 5); + y = sd->bl.y + (rand() % 10 - 5); + id = mob_once_spawn(sd, "this", x, y, "--ja--", i, 1, ""); + } + + return 0; +} + +/*========================================== + * @changelook by [Celest] + *------------------------------------------ + */ +int +atcommand_changelook(const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int i, j = 0, k = 0; + int pos[6] = { LOOK_HEAD_TOP,LOOK_HEAD_MID,LOOK_HEAD_BOTTOM,LOOK_WEAPON,LOOK_SHIELD,LOOK_SHOES }; + + if((i = sscanf(message, "%d %d", &j, &k)) < 1) { + clif_displaymessage(fd, "Usage: @changelook [<position>] <view id> -- [] = optional"); + clif_displaymessage(fd, "Position: 1-Top 2-Middle 3-Bottom 4-Weapon 5-Shield"); + return -1; + } else if (i == 2) { + if (j < 1) j = 1; + else if (j > 6) j = 6; // 6 = Shoes - for beta clients only perhaps + j = pos[j - 1]; + } else if (i == 1) { // position not defined, use HEAD_TOP as default + k = j; // swap + j = LOOK_HEAD_TOP; + } + + clif_changelook(&sd->bl,j,k); + + return 0; +} + +/*========================================== + *Turns on/off AutoLoot for a specific player + *------------------------------------------ + *by Upa-Kun + */ +int +atcommand_autoloot( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + nullpo_retr(-1, sd); + if (sd->autoloot) + { + sd->autoloot = 0; + clif_displaymessage(fd, "Autoloot is now off."); + } + else + { + sd->autoloot = 1; + clif_displaymessage(fd, "Autoloot is now on."); + } + return 0; +} + + /*========================================== * It is made to rain. *------------------------------------------ @@ -7273,13 +7653,16 @@ atcommand_rain( const char* command, const char* message) { int effno = 0; - effno = 161; nullpo_retr(-1, sd); - if (effno < 0 || map[sd->bl.m].flag.rain) - return -1; - - map[sd->bl.m].flag.rain=1; - clif_specialeffect(&sd->bl,effno,2); + effno = 161; + if (map[sd->bl.m].flag.rain) { + map[sd->bl.m].flag.rain=0; + clif_displaymessage(fd, "The rain has stopped."); + } else { + map[sd->bl.m].flag.rain=1; + clif_specialeffect(&sd->bl,effno,2); + clif_displaymessage(fd, "It is made to rain."); + } return 0; } /*========================================== @@ -7294,11 +7677,15 @@ atcommand_snow( int effno = 0; effno = 162; nullpo_retr(-1, sd); - if (effno < 0 || map[sd->bl.m].flag.snow) - return -1; + if (map[sd->bl.m].flag.snow) { + map[sd->bl.m].flag.snow=0; + clif_displaymessage(fd, "Snow has stopped falling."); + } else { + map[sd->bl.m].flag.snow=1; + clif_specialeffect(&sd->bl,effno,2); + clif_displaymessage(fd, "It is made to snow."); + } - map[sd->bl.m].flag.snow=1; - clif_specialeffect(&sd->bl,effno,2); return 0; } @@ -7314,11 +7701,14 @@ atcommand_sakura( int effno = 0; effno = 163; nullpo_retr(-1, sd); - if (effno < 0 || map[sd->bl.m].flag.sakura) - return -1; - - map[sd->bl.m].flag.sakura=1; - clif_specialeffect(&sd->bl,effno,2); + if (map[sd->bl.m].flag.sakura) { + map[sd->bl.m].flag.sakura=0; + clif_displaymessage(fd, "Cherry tree leaves is made to fall."); + } else { + map[sd->bl.m].flag.sakura=1; + clif_specialeffect(&sd->bl,effno,2); + clif_displaymessage(fd, "Cherry tree leaves is made to fall."); + } return 0; } @@ -7334,11 +7724,14 @@ atcommand_fog( int effno = 0; effno = 233; nullpo_retr(-1, sd); - if (effno < 0 || map[sd->bl.m].flag.fog) - return -1; - - map[sd->bl.m].flag.fog=1; - clif_specialeffect(&sd->bl,effno,2); + if (map[sd->bl.m].flag.fog) { + map[sd->bl.m].flag.fog=0; + clif_displaymessage(fd, "The fog has gone."); + } else { + map[sd->bl.m].flag.fog=1; + clif_specialeffect(&sd->bl,effno,2); + clif_displaymessage(fd, "Fog hangs over."); + } return 0; } @@ -7355,15 +7748,211 @@ atcommand_leaves( int effno = 0; effno = 333; nullpo_retr(-1, sd); - if (effno < 0 || map[sd->bl.m].flag.leaves) + if (map[sd->bl.m].flag.leaves) { + map[sd->bl.m].flag.leaves=0; + clif_displaymessage(fd, "Leaves no longer fall."); + } else { + map[sd->bl.m].flag.leaves=1; + clif_specialeffect(&sd->bl,effno,2); + clif_displaymessage(fd, "Fallen leaves fall."); + } + + return 0; +} + +/*========================================== + * Clearing Weather Effects by Dexity + *------------------------------------------ + */ +int +atcommand_clearweather( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + //int effno = 0; + nullpo_retr(-1, sd); + map[sd->bl.m].flag.rain=0; + map[sd->bl.m].flag.snow=0; + map[sd->bl.m].flag.sakura=0; + map[sd->bl.m].flag.fog=0; + map[sd->bl.m].flag.leaves=0; + //clif_specialeffect(&sd->bl,effno,2); // not required. [celest] + return 0; +} + +/*=============================================================== + * Sound Command - plays a sound for everyone! [Codemaster] + *--------------------------------------------------------------- + */ +int +atcommand_sound( + const int fd, struct map_session_data *sd, + const char *command, const char *message) +{ + char sound_file[100]; + + if(!message || !*message || sscanf(message, "%99[^\n]", sound_file) < 1) { + clif_displaymessage(fd, "Please, enter a sound filename. (usage: @sound <filename>)"); + return -1; + } + + memset(sound_file, '\0', sizeof(sound_file)); + if(sscanf(message, "%99[^\n]", sound_file) < 1) + return -1; + + if(strstr(sound_file, ".wav") == NULL) + strcat(sound_file, ".wav"); + + clif_soundeffectall(&sd->bl, sound_file,0); + + return 0; +} + +/*========================================== + * MOB Search + *------------------------------------------ + */ +int +atcommand_mobsearch( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char mob_name[100]; + int mob_id,map_id = 0; + + nullpo_retr(-1, sd); + + if (sscanf(message, "%99[^\n]", mob_name) < 0) + return -1; + + if ((mob_id = atoi(mob_name)) == 0) + mob_id = mobdb_searchname(mob_name); + if(mob_id !=-1 && (mob_id <= 1000 || mob_id >= 2000)){ + snprintf(atcmd_output, sizeof atcmd_output, "Invalid mob id %s!",mob_name); + clif_displaymessage(fd, atcmd_output); + return 0; + } + if(mob_id == atoi(mob_name) && mob_db[mob_id].jname) + strcpy(mob_name,mob_db[mob_id].jname); // --ja-- +// strcpy(mob_name,mob_db[mob_id].name); // --en-- + + map_id = sd->bl.m; + + snprintf(atcmd_output, sizeof atcmd_output, "Mob Search... %s %s", + mob_name, sd->mapname); + clif_displaymessage(fd, atcmd_output); + + map_foreachinarea(atmobsearch_sub, map_id, 0, 0, + map[map_id].xs, map[map_id].ys, BL_MOB, mob_id, fd); + + atmobsearch_sub(&sd->bl,0); // ”Ô†ƒŠƒZƒbƒg + + return 0; +} +/*========================================== + * ƒhƒƒbƒvƒAƒCƒeƒ€‚Ì‘|œ + *------------------------------------------ + */ +int +atcommand_cleanmap( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int i=0; + map_foreachinarea(atcommand_cleanmap_sub,sd->bl.m, + sd->bl.x-AREA_SIZE*2,sd->bl.y-AREA_SIZE*2, + sd->bl.x+AREA_SIZE*2,sd->bl.y+AREA_SIZE*2, + BL_ITEM,sd,&i); + clif_displaymessage(fd, "All dropped items have been cleaned up."); + return 0; +} + +/*========================================== + * NPC/PET‚ɘb‚³‚¹‚é + *------------------------------------------ + */ +int +atcommand_npctalk( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char name[100],mes[100]; + struct npc_data *nd; + + if (sscanf(message, "%s %99[^\n]", name, mes) < 2) + return -1; + + if (!(nd = npc_name2id(name))) + return -1; + + clif_message(&nd->bl, mes); + return 0; +} +int +atcommand_pettalk( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char mes[100],temp[100]; + struct pet_data *pd; + + nullpo_retr(-1, sd); + + if(!sd->status.pet_id || !(pd=sd->pd)) return -1; - map[sd->bl.m].flag.leaves=1; - clif_specialeffect(&sd->bl,effno,2); + if (sscanf(message, "%99[^\n]", mes) < 1) + return -1; + + snprintf(temp, sizeof temp ,"%s : %s",sd->pet.name,mes); + clif_message(&pd->bl, temp); + return 0; } + /*========================================== - * + * @users + * ƒT[ƒo[“à‚Ìl”ƒ}ƒbƒv‚ð•\ަ‚³‚¹‚é + * Žè”²‚«‚Ì‚½‚߉˜‚‚È‚Á‚Ä‚¢‚é‚͎̂d—l‚Å‚·B + *------------------------------------------ + */ + +static struct dbt *users_db; +static int users_all; + +static int atcommand_users_sub1(struct map_session_data* sd,va_list va) { + int users = (int)strdb_search(users_db,sd->mapname) + 1; + users_all++; + strdb_insert(users_db,sd->mapname,(void *)users); + return 0; +} + +static int atcommand_users_sub2(void* key,void* val,va_list va) { + char buf[256]; + struct map_session_data* sd = va_arg(va,struct map_session_data*); + sprintf(buf,"%s : %d (%d%%)",(char *)key,(int)val,(int)val * 100 / users_all); + clif_displaymessage(sd->fd,buf); + return 0; +} + +int +atcommand_users( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char buf[256]; + users_all = 0; + users_db = strdb_init(24); + clif_foreachclient(atcommand_users_sub1); + strdb_foreach(users_db,atcommand_users_sub2,sd); + sprintf(buf,"all : %d",users_all); + clif_displaymessage(fd,buf); + strdb_final(users_db,NULL); + return 0; +} + +/*========================================== + * *------------------------------------------ */ int @@ -7378,14 +7967,14 @@ atcommand_summon( int id = 0; struct mob_data *md; unsigned int tick=gettick(); - + nullpo_retr(-1, sd); if (!message || !*message) return -1; if (sscanf(message, "%99s", name) < 1) return -1; - + if ((mob_id = atoi(name)) == 0) mob_id = mobdb_searchname(name); if(mob_id == 0) @@ -7398,7 +7987,7 @@ atcommand_summon( if((md=(struct mob_data *)map_id2bl(id))){ md->master_id=sd->bl.id; md->state.special_mob_ai=1; - md->mode=mob_db[md->class].mode|0x04; + md->mode=mob_db[md->class_].mode|0x04; md->deletetimer=add_timer(tick+60000,mob_timer_delete,id,0); clif_misceffect2(&md->bl,344); } @@ -7424,9 +8013,10 @@ atcommand_adjcmdlvl( { int i, newlev; char cmd[100]; + nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d %s", &newlev, cmd) != 2) { - clif_displaymessage(fd, "usage: @adjcmdlvl <lvl> <command>."); + clif_displaymessage(fd, "Usage: @adjcmdlvl <lvl> <command>."); return -1; } @@ -7458,13 +8048,14 @@ atcommand_adjgmlvl( int newlev; char user[100]; struct map_session_data *pl_sd; + nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d %[^\r\n]", &newlev, user) != 2) { - clif_displaymessage(fd, "usage: @adjgmlvl <lvl> <user>."); + clif_displaymessage(fd, "Usage: @adjgmlvl <lvl> <user>."); return -1; } - if((pl_sd=map_nick2sd((char *) user)) == NULL) + if((pl_sd=map_nick2sd((char *) user)) == NULL) return -1; pc_set_gm_level(pl_sd->status.account_id, newlev); @@ -7478,7 +8069,7 @@ atcommand_adjgmlvl( * * Open a trade window with a remote player * - * If I have to jump to a remote player one more time, I am + * If I have to jump to a remote player one more time, I am * gonna scream! *------------------------------------------ */ @@ -7488,6 +8079,7 @@ atcommand_trade( const char* command, const char* message) { struct map_session_data *pl_sd = NULL; + nullpo_retr(-1, sd); if (!message || !*message) return -1; @@ -7509,13 +8101,14 @@ atcommand_setbattleflag( const char* command, const char* message) { char flag[128], value[128]; + nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%s %s", flag, value) != 2) { - clif_displaymessage(fd, "usage: @setbattleflag <flag> <value>."); + clif_displaymessage(fd, "Usage: @setbattleflag <flag> <value>."); return -1; } - if (battle_set_value(flag, value) == 0) + if (battle_set_value(flag, value) == 0) clif_displaymessage(fd, "unknown battle_config flag"); else clif_displaymessage(fd, "battle_config set as requested"); @@ -7533,13 +8126,14 @@ int atcommand_unmute( const char* command, const char* message) { struct map_session_data *pl_sd = NULL; + nullpo_retr(-1, sd); if (!message || !*message) return -1; if((pl_sd=map_nick2sd((char *) message)) != NULL) { if(pl_sd->sc_data[SC_NOCHAT].timer!=-1) { pl_sd->status.manner = 0; // have to set to 0 first [celest] - skill_status_change_end(&pl_sd->bl,SC_NOCHAT,-1); + status_change_end(&pl_sd->bl,SC_NOCHAT,-1); clif_displaymessage(sd->fd,"Player unmuted"); } else @@ -7558,9 +8152,9 @@ atcommand_uptime( const int fd, struct map_session_data* sd, const char* command, const char* message) { - char output[200]; long seconds = 0, day = 24*60*60, hour = 60*60, minute = 60, days = 0, hours = 0, minutes = 0; + nullpo_retr(-1, sd); seconds = (gettick()-ticks)/CLOCKS_PER_SEC; days = seconds/day; @@ -7569,9 +8163,11 @@ atcommand_uptime( seconds -= (seconds/hour>0)?(seconds/hour)*hour:0; minutes = seconds/minute; seconds -= (seconds/minute>0)?(seconds/minute)*minute:0; - - snprintf(output, sizeof(output), msg_table[245], days, hours, minutes, seconds); - clif_displaymessage(fd,output); + + snprintf(atcmd_output, sizeof(atcmd_output), msg_table[245], days, hours, minutes, seconds); + + clif_displaymessage(fd,atcmd_output); + return 0; } @@ -7586,7 +8182,8 @@ atcommand_changesex( const int fd, struct map_session_data* sd, const char* command, const char* message) { - chrif_changesex(sd->status.account_id, ((sd->status.sex+1)%2)); + nullpo_retr(-1, sd); + chrif_char_ask_name(sd->status.account_id,sd->status.name, 5,0,0,0,0,0,0); return 0; } @@ -7599,18 +8196,18 @@ int atcommand_mute( const char* command, const char* message) { struct map_session_data *pl_sd = NULL; - char character[100]; int manner; + nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%d %99[^\n]", &manner, character) < 1) { - clif_displaymessage(fd, "usage: @mute <time> <character name>."); + if (!message || !*message || sscanf(message, "%d %99[^\n]", &manner, atcmd_player_name) < 1) { + clif_displaymessage(fd, "Usage: @mute <time> <character name>."); return -1; } - if ((pl_sd = map_nick2sd(character)) != NULL) { + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { pl_sd->status.manner -= manner; if(pl_sd->status.manner < 0) - skill_status_change_start(&pl_sd->bl,SC_NOCHAT,0,0,0,0,0,0); + status_change_start(&pl_sd->bl,SC_NOCHAT,0,0,0,0,0,0); } else { clif_displaymessage(fd, msg_table[3]); // Character not found. @@ -7628,9 +8225,9 @@ int atcommand_refresh( const int fd, struct map_session_data* sd, const char* command, const char* message) { - nullpo_retr(-1, sd); - pc_setpos(sd, sd->mapname, sd->bl.x, sd->bl.y, 3); + //pc_setpos(sd, sd->mapname, sd->bl.x, sd->bl.y, 3); + clif_refresh(sd); return 0; } @@ -7647,7 +8244,7 @@ atcommand_petid(const int fd, struct map_session_data* sd, char temp0[100]; char temp1[100]; int cnt = 0, i = 0; - + nullpo_retr(-1, sd); if (!message || !*message) @@ -7663,7 +8260,7 @@ atcommand_petid(const int fd, struct map_session_data* sd, strcpy(temp0,pet_db[i].jname); strcpy(temp0, estr_lower(temp1)); if (strstr(temp1, searchtext) || strstr(temp0, searchtext) ) { - snprintf(temp0, sizeof(temp0), "ID: %i -- Name: %s", pet_db[i].class, + snprintf(temp0, sizeof(temp0), "ID: %i -- Name: %s", pet_db[i].class_, pet_db[i].jname); if (cnt >= 100) { // Only if there are custom pets clif_displaymessage(fd, "Be more specific, can't send more than" @@ -7690,15 +8287,17 @@ atcommand_identify( const int fd, struct map_session_data* sd, const char* command, const char* message) { - nullpo_retr(-1, sd); int i,num; + + nullpo_retr(-1, sd); + for(i=num=0;i<MAX_INVENTORY;i++){ if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify!=1){ num++; } } if (num > 0) { - clif_item_identify_list(sd); + clif_item_identify_list(sd); } else { clif_displaymessage(fd,"There are no items to appraise."); } @@ -7706,7 +8305,7 @@ atcommand_identify( } /*========================================== - * @gmotd (Global MOTD) + * @gmotd (Global MOTD) * by davidsiaw :P *------------------------------------------ */ @@ -7717,6 +8316,7 @@ atcommand_gmotd( { char buf[256]; FILE *fp; + nullpo_retr(-1, sd); if( (fp = fopen(motd_txt, "r"))!=NULL){ while (fgets(buf, 250, fp) != NULL){ int i; @@ -7744,10 +8344,632 @@ int atcommand_misceffect( if (sscanf(message, "%d", &effect) < 1) return -1; clif_misceffect(&sd->bl,effect); - + return 0; } +int charid2sessionid(int charid) +{ + int i; + int session_id=0; + struct map_session_data *pl_sd = NULL; + + for(i=0;i<fd_max;i++){ + if(session[i] && (pl_sd= (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth){ + if (pl_sd->status.char_id==charid) { session_id = i; break; } + } + } + + return session_id; +} + +int accountid2sessionid(int accountid) +{ + int i; + int session_id=0; + struct map_session_data *pl_sd = NULL; + + for(i=0;i<fd_max;i++){ + if(session[i] && (pl_sd= (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth){ + if (pl_sd->status.account_id==accountid) { session_id = i; break; } + } + } + + return session_id; +} + + +/*========================================== + * Jump to a player by PID number + * Original by Dino9021 + * Added in by nsstrunks + *------------------------------------------ + */ + +int atcommand_jumptoid( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int cid=0; + int session_id=0; + struct map_session_data *pl_sd; + + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + if (!message || (cid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, "Please, enter a player CID (usage: @jumptoid/@warptoid/@gotoid <char id>)."); + return -1; + } + + cid=atoi(message); + + if ((session_id=charid2sessionid(cid))!=0) + { + if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) { + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + clif_displaymessage(fd, msg_table[247]); + return -1; + } + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + clif_displaymessage(fd, msg_table[248]); + return -1; + } + pc_setpos(sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y, 3); + sprintf(atcmd_output, msg_table[4], pl_sd->status.name); // Jump to %s + clif_displaymessage(fd, atcmd_output); + } else { + clif_displaymessage(fd, msg_table[154]); // Character not found. + return -1; + } + } + else + { + clif_displaymessage(fd,msg_table[3]); + } + //printf("Session_id = %d, cid = %d\n",session_id,cid); + + return 0; +} + +/*========================================== + * Jump to a player by PID number + * Original by Dino9021 + * Added in by nsstrunks + *------------------------------------------ + */ + +int atcommand_jumptoid2( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int aid=0; + int session_id=0; + struct map_session_data *pl_sd; + + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + if (!message || (aid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, "Please, enter a player AID (usage: @jumptoid/@warptoid/@gotoid <account id>)."); + return -1; + } + + aid=atoi(message); + + if ((session_id=accountid2sessionid(aid))!=0) + { + if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) { + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + clif_displaymessage(fd, msg_table[247]); + return -1; + } + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + clif_displaymessage(fd, msg_table[248]); + return -1; + } + pc_setpos(sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y, 3); + sprintf(atcmd_output, msg_table[4], pl_sd->status.name); // Jump to %s + clif_displaymessage(fd, atcmd_output); + } else { + clif_displaymessage(fd, msg_table[154]); // Character not found. + return -1; + } + } + else + { + clif_displaymessage(fd,msg_table[3]); + } + //printf("Session_id = %d, aid = %d\n",session_id,aid); + + return 0; +} + +/*========================================== + * Recall a player by PID number + * Original by Dino9021 + * Added in by nsstrunks + *------------------------------------------ + */ +int atcommand_recallid( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int cid=0; + int session_id=0; + struct map_session_data *pl_sd; + + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + if (!message || (cid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, "Please, enter a player CID (usage: @recallid <char id>)."); + return -1; + } + + cid=atoi(message); + + if ((session_id=charid2sessionid(cid))!=0) + { + if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) { + if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can recall only lower or same level + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + clif_displaymessage(fd, msg_table[247]); + return -1; + } + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + clif_displaymessage(fd, msg_table[248]); + return -1; + } + pc_setpos(pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2); + sprintf(atcmd_output, msg_table[46], pl_sd->status.name); // Jump to %s + clif_displaymessage(fd, atcmd_output); + } else { + clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[154]); // Character not found. + return -1; + } + } + else + { + clif_displaymessage(fd,msg_table[3]); + } + //printf("Session_id = %d, cid = %d\n",session_id,cid); + + return 0; +} + +/*========================================== + * Recall a player by PID number + * Original by Dino9021 + * Added in by nsstrunks + *------------------------------------------ + */ +int atcommand_recallid2( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int aid=0; + int session_id=0; + struct map_session_data *pl_sd; + + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + if (!message || (aid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, "Please, enter a player AID (usage: @recallid2 <account id>)."); + return -1; + } + + aid=atoi(message); + + if ((session_id=accountid2sessionid(aid))!=0) + { + if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) { + if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can recall only lower or same level + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + clif_displaymessage(fd, msg_table[247]); + return -1; + } + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + clif_displaymessage(fd, msg_table[248]); + return -1; + } + pc_setpos(pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2); + sprintf(atcmd_output, msg_table[46], pl_sd->status.name); // Jump to %s + clif_displaymessage(fd, atcmd_output); + } else { + clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[154]); // Character not found. + return -1; + } + } + else + { + clif_displaymessage(fd,msg_table[3]); + } + //printf("Session_id = %d, aid = %d\n",session_id,aid); + + return 0; +} + +/*========================================== + * Kick a player by PID number + * Original by Dino9021 + * Added in by nsstrunks + *------------------------------------------ + */ +int atcommand_kickid( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct map_session_data *pl_sd; + int cid=0; + int session_id=0; + + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + + if (!message || (cid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, "Please, enter a player CID (usage: @kickid <char id>)."); + return -1; + } + + cid=atoi(message); + + if ((session_id=charid2sessionid(cid))!=0) + { + if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) { + if (pc_isGM(sd) >= pc_isGM(pl_sd)) // you can kick only lower or same gm level + clif_GM_kick(sd, pl_sd, 1); + else { + clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[3]); // Character not found. + return -1; + } + + } + else + { + clif_displaymessage(fd,msg_table[3]); + } + //printf("Session_id = %d, cid = %d\n",session_id,cid); + + return 0; +} + +/*========================================== + * Kick a player by PID number + * Original by Dino9021 + * Added in by nsstrunks + *------------------------------------------ + */ +int atcommand_kickid2( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct map_session_data *pl_sd; + int aid=0; + int session_id=0; + + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + + if (!message || (aid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, "Please, enter a player AID (usage: @kickid2 <account id>)."); + return -1; + } + + aid=atoi(message); + + if ((session_id=accountid2sessionid(aid))!=0) + { + if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) { + if (pc_isGM(sd) >= pc_isGM(pl_sd)) // you can kick only lower or same gm level + clif_GM_kick(sd, pl_sd, 1); + else { + clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[3]); // Character not found. + return -1; + } + + } + else + { + clif_displaymessage(fd,msg_table[3]); + } + //printf("Session_id = %d, aid = %d\n",session_id,aid); + + return 0; +} + +/*========================================== + * Revive a player by PID number + * Original by Dino9021 + * Added in by nsstrunks + *------------------------------------------ + */ +int atcommand_reviveid( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int cid=0; + int session_id=0; + struct map_session_data *pl_sd; + + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + + if (!message || (cid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, "Please, enter a player CID (usage: @reviveid <char id>)."); + return -1; + } + + cid=atoi(message); + + if ((session_id=charid2sessionid(cid))!=0) + { + if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) { + pl_sd->status.hp = pl_sd->status.max_hp; + pc_setstand(pl_sd); + if (battle_config.pc_invincible_time > 0) + pc_setinvincibletimer(sd, battle_config.pc_invincible_time); + clif_updatestatus(pl_sd, SP_HP); + clif_updatestatus(pl_sd, SP_SP); + clif_resurrection(&pl_sd->bl, 1); + clif_displaymessage(fd, msg_table[51]); // Character revived. + } else { + clif_displaymessage(fd, msg_table[3]); // Character not found. + return -1; + } + + } + else + { + clif_displaymessage(fd,msg_table[3]); + } + //printf("Session_id = %d, cid = %d\n",session_id,cid); + + + return 0; +} + +/*========================================== + * Revive a player by PID number + * Original by Dino9021 + * Added in by nsstrunks + *------------------------------------------ + */ +int atcommand_reviveid2( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int aid=0; + int session_id=0; + struct map_session_data *pl_sd; + + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + + if (!message || (aid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, "Please, enter a player AID (usage: @reviveid2 <account id>)."); + return -1; + } + + aid=atoi(message); + + if ((session_id=accountid2sessionid(aid))!=0) + { + if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) { + pl_sd->status.hp = pl_sd->status.max_hp; + pc_setstand(pl_sd); + if (battle_config.pc_invincible_time > 0) + pc_setinvincibletimer(sd, battle_config.pc_invincible_time); + clif_updatestatus(pl_sd, SP_HP); + clif_updatestatus(pl_sd, SP_SP); + clif_resurrection(&pl_sd->bl, 1); + clif_displaymessage(fd, msg_table[51]); // Character revived. + } else { + clif_displaymessage(fd, msg_table[3]); // Character not found. + return -1; + } + + } + else + { + clif_displaymessage(fd,msg_table[3]); + } + //printf("Session_id = %d, aid = %d\n",session_id,aid); + + + return 0; +} + +/*========================================== + * Kill a player by PID number + * Original by Dino9021 + * Added in by nsstrunks + *------------------------------------------ + */ +int atcommand_killid( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int cid=0; + int session_id=0; + struct map_session_data *pl_sd; + + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + + if (!message || (cid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, "Please, enter a player CID (usage: @killid <char id>)."); + return -1; + } + + cid=atoi(message); + + if ((session_id=charid2sessionid(cid))!=0) + { + if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) { + if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kill only lower or same level + pc_damage(NULL, pl_sd, pl_sd->status.hp + 1); + clif_displaymessage(fd, msg_table[14]); // Character killed. + } else { + clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[3]); // Character not found. + return -1; + } + + } + else + { + clif_displaymessage(fd,msg_table[3]); + } + //printf("Session_id = %d, cid = %d\n",session_id,cid); + + return 0; +} + +/*========================================== + * Kill a player by PID number + * Original by Dino9021 + * Added in by nsstrunks + *------------------------------------------ + */ +int atcommand_killid2( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int aid=0; + int session_id=0; + struct map_session_data *pl_sd; + + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + + if (!message || (aid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, "Please, enter a player AID (usage: @killid2 <account id>)."); + return -1; + } + + aid=atoi(message); + + if ((session_id=accountid2sessionid(aid))!=0) + { + if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) { + if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kill only lower or same level + pc_damage(NULL, pl_sd, pl_sd->status.hp + 1); + clif_displaymessage(fd, msg_table[14]); // Character killed. + } else { + clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[3]); // Character not found. + return -1; + } + + } + else + { + clif_displaymessage(fd,msg_table[3]); + } + //printf("Session_id = %d, aid = %d\n",session_id,aid); + + return 0; +} + +/*========================================== + * Make a player killable, by PID + * Original by Dino9021 + * Added in by nsstrunks + *------------------------------------------ + */ +int +atcommand_charkillableid( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct map_session_data *pl_sd = NULL; + int cid=0; + int session_id=0; + + if (!message || (cid = atoi(message)) == 0 || !*message) + return -1; + + cid=atoi(message); + + if ((session_id=charid2sessionid(cid))!=0) + { + if((pl_sd= (struct map_session_data *) session[session_id]->session_data) == NULL) + return -1; + + pl_sd->special_state.killable = !pl_sd->special_state.killable; + + if(pl_sd->special_state.killable) + clif_displaymessage(fd, "The player is now killable"); + else + clif_displaymessage(fd, "The player is no longer killable"); + } + else + { + clif_displaymessage(fd,msg_table[3]); + } + //printf("Session_id = %d, cid = %d\n",session_id,cid); + return 0; +} + + +/*========================================== + * Make a player killable, by PID + * Original by Dino9021 + * Added in by nsstrunks + *------------------------------------------ + */ +int +atcommand_charkillableid2( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct map_session_data *pl_sd = NULL; + int aid=0; + int session_id=0; + + if (!message || (aid = atoi(message)) == 0 || !*message) + return -1; + + aid=atoi(message); + + if ((session_id=accountid2sessionid(aid))!=0) + { + if((pl_sd= (struct map_session_data *) session[session_id]->session_data) == NULL) + return -1; + + pl_sd->special_state.killable = !pl_sd->special_state.killable; + + if(pl_sd->special_state.killable) + clif_displaymessage(fd, "The player is now killable"); + else + clif_displaymessage(fd, "The player is no longer killable"); + } + else + { + clif_displaymessage(fd,msg_table[3]); + } + //printf("Session_id = %d, aid = %d\n",session_id,aid); + return 0; +} + #ifndef TXT_ONLY /* Begin SQL-Only commands */ /*========================================== @@ -7767,7 +8989,7 @@ int atcommand_listmail( mail_check(sd,3); else if(strlen(command)==9) mail_check(sd,2); - else + else mail_check(sd,1); return 0; } @@ -7818,7 +9040,7 @@ int atcommand_sendmail( if(strlen(command)==17) mail_send(sd,name,text,1); - else + else mail_send(sd,name,text,0); return 0; @@ -7837,8 +9059,171 @@ int atcommand_refreshonline( nullpo_retr(-1, sd); char_online_check(); - + return 0; } #endif /* end sql only */ + +/*========================================== + * Show Monster DB Info v 1.0 + * originally by [Lupus] eAthena + *------------------------------------------ + */ +int atcommand_mobinfo( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + unsigned char msize[3][7] = {"Small", "Medium", "Large"}; + unsigned char mrace[12][11] = {"Formless", "Undead", "Beast", "Plant", "Insect", "Fish", "Demon", "Demi-Human", "Angel", "Dragon", "Boss", "Non-Boss"}; + unsigned char melement[11][8] = {"None", "Neutral", "Water", "Earth", "Fire", "Wind", "Poison", "Holy", "Dark", "Ghost", "Undead"}; + char atcmd_output2[200]; + struct item_data *item_data; + struct mob_db *mob; + int mob_id; + int i, j; + + memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output2, '\0', sizeof(atcmd_output2)); + + if (!message || !*message) { + clif_displaymessage(fd, "Please, enter a Monster/NPC name/id (usage: @mobinfo <monster_name_or_monster_ID>)."); + return -1; + } + + // If monster identifier/name argument is a name + if ((mob_id = mobdb_searchname(message)) == 0) // check name first (to avoid possible name begining by a number) + mob_id = mobdb_checkid(atoi(message)); + + if (mob_id == 0) { + clif_displaymessage(fd, msg_table[40]); // Invalid monster ID or name. + return -1; + } + + mob = &mob_db[mob_id]; + + // stats + if (mob->mexp) + sprintf(atcmd_output, "Monster (MVP): '%s'/'%s' (%d)", mob->name, mob->jname, mob_id); + else + sprintf(atcmd_output, "Monster: '%s'/'%s' (%d)", mob->name, mob->jname, mob_id); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, " Level:%d HP:%d SP:%d Base EXP:%d Job EXP:%d", mob->lv, mob->max_hp, mob->max_sp, mob->base_exp, mob->job_exp); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, " DEF:%d MDEF:%d STR:%d AGI:%d VIT:%d INT:%d DEX:%d LUK:%d", mob->def, mob->mdef, mob->str, mob->agi, mob->vit, mob->int_, mob->dex, mob->luk); + clif_displaymessage(fd, atcmd_output); + if (mob->element < 20) { + //Element - None, Level 0 + i = 0; + j = 0; + } else { + i = mob->element % 20 + 1; + j = mob->element / 20; + } + sprintf(atcmd_output, " ATK:%d~%d Range:%d~%d~%d Size:%s Race: %s Element: %s (Lv:%d)", mob->atk1, mob->atk2, mob->range, mob->range2 , mob->range3, msize[mob->size], mrace[mob->race], melement[i], j); + clif_displaymessage(fd, atcmd_output); + // drops + clif_displaymessage(fd, " Drops:"); + strcpy(atcmd_output, " "); + j = 0; + for (i = 0; i < 10; i++) { + if (mob->dropitem[i].nameid <= 0 || (item_data = itemdb_search(mob->dropitem[i].nameid)) == NULL) + continue; + if (mob->dropitem[i].p > 0) { + sprintf(atcmd_output2, " - %s %02.02f%%", item_data->name, (float)mob->dropitem[i].p / 100); + strcat(atcmd_output, atcmd_output2); + if (++j % 3 == 0) { + clif_displaymessage(fd, atcmd_output); + strcpy(atcmd_output, " "); + } + } + } + if (j == 0) + clif_displaymessage(fd, "This monster has no drop."); + else if (j % 3 != 0) + clif_displaymessage(fd, atcmd_output); + // mvp + if (mob->mexp) { + sprintf(atcmd_output, " MVP Bonus EXP:%d %02.02f%%", mob->mexp, (float)mob->mexpper / 100); + clif_displaymessage(fd, atcmd_output); + strcpy(atcmd_output, " MVP Items:"); + j = 0; + for (i = 0; i < 3; i++) { + if (mob->mvpitem[i].nameid <= 0 || (item_data = itemdb_search(mob->mvpitem[i].nameid)) == NULL) + continue; + if (mob->mvpitem[i].p > 0) { + j++; + if (j == 1) + sprintf(atcmd_output2, " %s %02.02f%%", item_data->name, (float)mob->mvpitem[i].p / 100); + else + sprintf(atcmd_output2, " - %s %02.02f%%", item_data->name, (float)mob->mvpitem[i].p / 100); + strcat(atcmd_output, atcmd_output2); + } + } + if (j == 0) + clif_displaymessage(fd, "This monster has no MVP drop."); + else + clif_displaymessage(fd, atcmd_output); + } + + return 0; +} + +/*========================================== + * @adopt by [Veider] + * + * adopt a novice + *------------------------------------------ + */ +int +atcommand_adopt(const int fd, struct map_session_data* sd, +const char* command, const char* message) +{ + struct map_session_data *pl_sd1 = NULL; + struct map_session_data *pl_sd2 = NULL; + struct map_session_data *pl_sd3 = NULL; + char player1[255], player2[255], player3[255]; + + nullpo_retr(-1, sd); + + if (!message || !*message) + return -1; + + if (sscanf(message, "%[^,],%[^,],%[^\r\n]", player1, player2, player3) != 3) { + clif_displaymessage(fd, "usage: @adopt <player1> <player2> <player3>."); + return -1; + } + + printf("Adopting: --%s--%s--%s--\n",player1,player2,player3); + + if((pl_sd1=map_nick2sd((char *) player1)) == NULL) { + sprintf(player2, "Cannot find player %s online", player1); + clif_displaymessage(fd, player2); + return -1; + } + + if((pl_sd2=map_nick2sd((char *) player2)) == NULL) { + sprintf(player1, "Cannot find player %s online", player2); + clif_displaymessage(fd, player1); + return -1; + } + + if((pl_sd3=map_nick2sd((char *) player3)) == NULL) { + sprintf(player1, "Cannot find player %s online", player3); + clif_displaymessage(fd, player1); + return -1; + } + + if((pl_sd1->status.base_level < 70) || (pl_sd2->status.base_level < 70)){ + clif_displaymessage(fd, "They are too young to be parents!"); + return -1; + } + + if (pc_adoption(pl_sd1, pl_sd2, pl_sd3) == 0) { + clif_displaymessage(fd, "They are family.. wish them luck"); + return 0; + } + else + return -1; +} + diff --git a/src/map/atcommand.h b/src/map/atcommand.h index 3d84cd5b9..1160dccb7 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -112,20 +112,20 @@ enum AtCommandType { AtCommand_CharSkReset, AtCommand_CharStReset, //by chbrules - AtCommand_CharModel, + AtCommand_CharModel, AtCommand_CharSKPoint, - AtCommand_CharSTPoint, - AtCommand_CharZeny, + AtCommand_CharSTPoint, +// AtCommand_CharZeny, //now #zeny AtCommand_RecallAll, AtCommand_ReloadItemDB, AtCommand_ReloadMobDB, AtCommand_ReloadSkillDB, -#ifndef TXT_ONLY - AtCommand_Rehash, -#else /* TXT_ONLY */ AtCommand_ReloadScript, -#endif /* TXT_ONLY */ AtCommand_ReloadGMDB, + AtCommand_ReloadAtcommand, + AtCommand_ReloadBattleConf, + AtCommand_ReloadStatusDB, + AtCommand_ReloadPcDB, AtCommand_MapInfo, AtCommand_Dye, AtCommand_Hstyle, @@ -143,8 +143,9 @@ enum AtCommandType { AtCommand_RepairAll, // [Valaris] AtCommand_GuildRecall, // by Yor AtCommand_PartyRecall, // by Yor -// AtCommand_Nuke, // [Valaris] + AtCommand_Nuke, // [Valaris] AtCommand_Enablenpc, + AtCommand_Hidenpc, AtCommand_Disablenpc, AtCommand_ServerTime, // by Yor AtCommand_CharDelItem, // by Yor @@ -157,8 +158,8 @@ enum AtCommandType { AtCommand_EMail, // by Yor AtCommand_Hatch, AtCommand_Effect, // by Apple - AtCommand_Char_Item_List, // by Yor - AtCommand_Char_Storage_List, // by Yor +// AtCommand_Char_Item_List, // by Yor, now #itemlist +// AtCommand_Char_Storage_List, // by Yor, now #storagelist AtCommand_Char_Cart_List, // by Yor AtCommand_AddWarp, // by MouseJstr AtCommand_Follow, // by MouseJstr @@ -168,10 +169,7 @@ enum AtCommandType { AtCommand_NpcMove, // by MouseJstr AtCommand_Killable, // by MouseJstr AtCommand_CharKillable, // by MouseJstr - AtCommand_Chareffect, // by MouseJstr - AtCommand_Chardye, // by MouseJstr - AtCommand_Charhairstyle, // by MouseJstr - AtCommand_Charhaircolor, // by MouseJstr +// AtCommand_Chareffect, // by MouseJstr, now #effect AtCommand_Dropall, // by MouseJstr AtCommand_Chardropall, // by MouseJstr AtCommand_Storeall, // by MouseJstr @@ -190,6 +188,7 @@ enum AtCommandType { AtCommand_Send, AtCommand_SetBattleFlag, AtCommand_UnMute, + AtCommand_Clearweather, // by Dexity AtCommand_UpTime, // by MC Cameri AtCommand_ChangeSex, // by MC Cameri AtCommand_Mute, // [celest] @@ -200,9 +199,14 @@ enum AtCommandType { AtCommand_Identify, // by MC Cameri AtCommand_Gmotd, // Added by MC Cameri, created by davidsiaw AtCommand_MiscEffect, // by MC Cameri + AtCommand_MobSearch, + AtCommand_CleanMap, + AtCommand_NpcTalk, + AtCommand_PetTalk, + AtCommand_Users, // SQL-only commands start -#ifndef TXT_ONLY +#ifndef TXT_ONLY AtCommand_CheckMail, // [Valaris] AtCommand_ListMail, // [Valaris] AtCommand_ListNewMail, // [Valaris] @@ -210,12 +214,40 @@ enum AtCommandType { AtCommand_SendMail, // [Valaris] AtCommand_DeleteMail, // [Valaris] AtCommand_SendPriorityMail, // [Valaris] - AtCommand_Sound, // [Valaris] +// AtCommand_Sound, // [Valaris] AtCommand_RefreshOnline, // [Valaris] // SQL-only commands end #endif AtCommand_SkillTree, // by MouseJstr - + AtCommand_Marry, // by MouseJstr + AtCommand_Divorce, // by MouseJstr + AtCommand_Rings, // by MouseJstr + AtCommand_Grind, // by MouseJstr + AtCommand_Grind2, // by MouseJstr + + AtCommand_DMStart, // by MouseJstr + AtCommand_DMTick, // by MouseJstr + + AtCommand_JumpToId, // by Dino9021 + AtCommand_JumpToId2, // by Dino9021 + AtCommand_RecallId, // by Dino9021 + AtCommand_RecallId2, // by Dino9021 + AtCommand_KickId, // by Dino9021 + AtCommand_KickId2, // by Dino9021 + AtCommand_ReviveId, // by Dino9021 + AtCommand_ReviveId2, // by Dino9021 + AtCommand_KillId, // by Dino9021 + AtCommand_KillId2, // by Dino9021 + AtCommand_CharKillableId, // by Dino9021 + AtCommand_CharKillableId2, // by Dino9021 + AtCommand_Sound, + AtCommand_UndisguiseAll, + AtCommand_DisguiseAll, + AtCommand_ChangeLook, + AtCommand_AutoLoot, //by Upa-Kun + AtCommand_MobInfo, //by Lupus + AtCommand_Adopt, // by Veider + // end AtCommand_Unknown, AtCommand_MAX @@ -235,6 +267,7 @@ AtCommandType is_atcommand(const int fd, struct map_session_data* sd, const char* message, int gmlvl); AtCommandType atcommand( + struct map_session_data *sd, const int level, const char* message, AtCommandInfo* info); int get_atcommand_level(const AtCommandType type); @@ -248,11 +281,12 @@ int atcommand_recall(const int fd, struct map_session_data* sd, const char* comm int atcommand_config_read(const char *cfgName); int msg_config_read(const char *cfgName); +void do_final_msg(); char *estr_lower(char *str); -char * job_name(int class); -int e_mail_check(unsigned char *email); +char * job_name(int class_); +int e_mail_check(char *email); #endif diff --git a/src/map/battle.c b/src/map/battle.c index 00ca5a9e0..077e5fc9b 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -12,6 +12,7 @@ #include "map.h" #include "pc.h" +#include "status.h" #include "skill.h" #include "mob.h" #include "itemdb.h" @@ -55,1259 +56,21 @@ int battle_counttargeted(struct block_list *bl,struct block_list *src,int target return mob_counttargeted((struct mob_data *)bl,src,target_lv); return 0; } -/*========================================== - * ‘ÎÛ‚ÌClass‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_class(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return ((struct mob_data *)bl)->class; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data *)bl)->status.class; - else if(bl->type==BL_PET && (struct pet_data *)bl) - return ((struct pet_data *)bl)->class; - else - return 0; -} -/*========================================== - * ‘ÎÛ‚Ì•ûŒü‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_dir(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return ((struct mob_data *)bl)->dir; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data *)bl)->dir; - else if(bl->type==BL_PET && (struct pet_data *)bl) - return ((struct pet_data *)bl)->dir; - else - return 0; -} -/*========================================== - * ‘Îۂ̃Œƒxƒ‹‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_lv(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return ((struct mob_data *)bl)->level; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data *)bl)->status.base_level; - else if(bl->type==BL_PET && (struct pet_data *)bl) - return ((struct pet_data *)bl)->msd->pet.level; - else - return 0; -} -/*========================================== - * ‘ÎÛ‚ÌŽË’ö‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_range(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return mob_db[((struct mob_data *)bl)->class].range; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data *)bl)->attackrange; - else if(bl->type==BL_PET && (struct pet_data *)bl) - return mob_db[((struct pet_data *)bl)->class].range; - else - return 0; -} -/*========================================== - * ‘ÎÛ‚ÌHP‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_hp(struct block_list *bl) -{ - nullpo_retr(1, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return ((struct mob_data *)bl)->hp; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data *)bl)->status.hp; - else - return 1; -} -/*========================================== - * ‘ÎÛ‚ÌMHP‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_max_hp(struct block_list *bl) -{ - nullpo_retr(1, bl); - if(bl->type==BL_PC && ((struct map_session_data *)bl)) - return ((struct map_session_data *)bl)->status.max_hp; - else { - struct status_change *sc_data=battle_get_sc_data(bl); - int max_hp=1; - if(bl->type==BL_MOB && ((struct mob_data*)bl)) { - max_hp = mob_db[((struct mob_data*)bl)->class].max_hp; - if(battle_config.mobs_level_up) // mobs leveling up increase [Valaris] - max_hp+=(((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv)*battle_get_vit(bl); - if(mob_db[((struct mob_data*)bl)->class].mexp > 0) { - if(battle_config.mvp_hp_rate != 100) - max_hp = (max_hp * battle_config.mvp_hp_rate)/100; - } - else { - if(battle_config.monster_hp_rate != 100) - max_hp = (max_hp * battle_config.monster_hp_rate)/100; - } - } - else if(bl->type==BL_PET && ((struct pet_data*)bl)) { - max_hp = mob_db[((struct pet_data*)bl)->class].max_hp; - if(mob_db[((struct pet_data*)bl)->class].mexp > 0) { - if(battle_config.mvp_hp_rate != 100) - max_hp = (max_hp * battle_config.mvp_hp_rate)/100; - } - else { - if(battle_config.monster_hp_rate != 100) - max_hp = (max_hp * battle_config.monster_hp_rate)/100; - } - } - if(sc_data) { - if(sc_data[SC_APPLEIDUN].timer!=-1) - max_hp += ((5+sc_data[SC_APPLEIDUN].val1*2+((sc_data[SC_APPLEIDUN].val2+1)>>1) - +sc_data[SC_APPLEIDUN].val3/10) * max_hp)/100; - } - if(max_hp < 1) max_hp = 1; - return max_hp; - } - return 1; -} -/*========================================== - * ‘ÎÛ‚ÌStr‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_str(struct block_list *bl) -{ - int str=0; - struct status_change *sc_data; - - nullpo_retr(0, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_MOB && ((struct mob_data *)bl)) { - str = mob_db[((struct mob_data *)bl)->class].str; - if(battle_config.mobs_level_up) // mobs leveling up increase [Valaris] - str+=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv; - } - else if(bl->type==BL_PC && ((struct map_session_data *)bl)) - return ((struct map_session_data *)bl)->paramc[0]; - else if(bl->type==BL_PET && ((struct pet_data *)bl)) - str = mob_db[((struct pet_data *)bl)->class].str; - - if(sc_data) { - if(sc_data[SC_LOUD].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1 && bl->type != BL_PC) - str += 4; - if( sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC){ // ƒuƒŒƒbƒVƒ“ƒO - int race=battle_get_race(bl); - if(battle_check_undead(race,battle_get_elem_type(bl)) || race==6 ) str >>= 1; // ˆ« –‚/•sŽ€ - else str += sc_data[SC_BLESSING].val1; // ‚»‚Ì‘¼ - } - if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // ƒgƒDƒ‹[ƒTƒCƒg - str += 5; - } - if(str < 0) str = 0; - return str; -} -/*========================================== - * ‘ÎÛ‚ÌAgi‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ - -int battle_get_agi(struct block_list *bl) -{ - int agi=0; - struct status_change *sc_data; - - nullpo_retr(0, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) { - agi=mob_db[((struct mob_data *)bl)->class].agi; - if(battle_config.mobs_level_up) // increase of mobs leveling up [Valaris] - agi+=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv; - } - else if(bl->type==BL_PC && (struct map_session_data *)bl) - agi=((struct map_session_data *)bl)->paramc[1]; - else if(bl->type==BL_PET && (struct pet_data *)bl) - agi=mob_db[((struct pet_data *)bl)->class].agi; - - if(sc_data) { - if( sc_data[SC_INCREASEAGI].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1 && - bl->type != BL_PC) // ‘¬“x‘‰Á(PC‚Ípc.c‚Å) - agi += 2+sc_data[SC_INCREASEAGI].val1; - - if(sc_data[SC_CONCENTRATE].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1 && bl->type != BL_PC) - agi += agi*(2+sc_data[SC_CONCENTRATE].val1)/100; - - if(sc_data[SC_DECREASEAGI].timer!=-1) // ‘¬“xŒ¸ - agi -= 2+sc_data[SC_DECREASEAGI].val1; - - if(sc_data[SC_QUAGMIRE].timer!=-1 ) { // ƒNƒ@ƒOƒ}ƒCƒA - //agi >>= 1; - int agib = agi*(sc_data[SC_QUAGMIRE].val1*10)/100; - agi -= agib > 50 ? 50 : agib; - } - if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // ƒgƒDƒ‹[ƒTƒCƒg - agi += 5; - } - if(agi < 0) agi = 0; - return agi; -} -/*========================================== - * ‘ÎÛ‚ÌVit‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_vit(struct block_list *bl) -{ - int vit=0; - struct status_change *sc_data; - - nullpo_retr(0, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) { - vit=mob_db[((struct mob_data *)bl)->class].vit; - if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris] - vit+=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv; - } - else if(bl->type==BL_PC && (struct map_session_data *)bl) - vit=((struct map_session_data *)bl)->paramc[2]; - else if(bl->type==BL_PET && (struct pet_data *)bl) - vit=mob_db[((struct pet_data *)bl)->class].vit; - if(sc_data) { - if(sc_data[SC_STRIPARMOR].timer != -1 && bl->type!=BL_PC) - vit = vit*60/100; - if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // ƒgƒDƒ‹[ƒTƒCƒg - vit += 5; - } - - if(vit < 0) vit = 0; - return vit; -} -/*========================================== - * ‘ÎÛ‚ÌInt‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_int(struct block_list *bl) -{ - int int_=0; - struct status_change *sc_data; - - nullpo_retr(0, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_MOB && (struct mob_data *)bl){ - int_=mob_db[((struct mob_data *)bl)->class].int_; - if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris] - int_+=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv; - } - else if(bl->type==BL_PC && (struct map_session_data *)bl) - int_=((struct map_session_data *)bl)->paramc[3]; - else if(bl->type==BL_PET && (struct pet_data *)bl) - int_=mob_db[((struct pet_data *)bl)->class].int_; - - if(sc_data) { - if( sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC){ // ƒuƒŒƒbƒVƒ“ƒO - int race=battle_get_race(bl); - if(battle_check_undead(race,battle_get_elem_type(bl)) || race==6 ) int_ >>= 1; // ˆ« –‚/•sŽ€ - else int_ += sc_data[SC_BLESSING].val1; // ‚»‚Ì‘¼ - } - if( sc_data[SC_STRIPHELM].timer != -1 && bl->type != BL_PC) - int_ = int_*60/100; - if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // ƒgƒDƒ‹[ƒTƒCƒg - int_ += 5; - } - if(int_ < 0) int_ = 0; - return int_; -} -/*========================================== - * ‘ÎÛ‚ÌDex‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_dex(struct block_list *bl) -{ - int dex=0; - struct status_change *sc_data; - - nullpo_retr(0, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) { - dex=mob_db[((struct mob_data *)bl)->class].dex; - if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris] - dex+=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv; - } - else if(bl->type==BL_PC && (struct map_session_data *)bl) - dex=((struct map_session_data *)bl)->paramc[4]; - else if(bl->type==BL_PET && (struct pet_data *)bl) - dex=mob_db[((struct pet_data *)bl)->class].dex; - - if(sc_data) { - if(sc_data[SC_CONCENTRATE].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1 && bl->type != BL_PC) - dex += dex*(2+sc_data[SC_CONCENTRATE].val1)/100; - - if( sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC){ // ƒuƒŒƒbƒVƒ“ƒO - int race=battle_get_race(bl); - if(battle_check_undead(race,battle_get_elem_type(bl)) || race==6 ) dex >>= 1; // ˆ« –‚/•sŽ€ - else dex += sc_data[SC_BLESSING].val1; // ‚»‚Ì‘¼ - } - - if(sc_data[SC_QUAGMIRE].timer!=-1 ) { // ƒNƒ@ƒOƒ}ƒCƒA - // dex >>= 1; - int dexb = dex*(sc_data[SC_QUAGMIRE].val1*10)/100; - dex -= dexb > 50 ? 50 : dexb; - } - if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // ƒgƒDƒ‹[ƒTƒCƒg - dex += 5; - } - if(dex < 0) dex = 0; - return dex; -} -/*========================================== - * ‘ÎÛ‚ÌLuk‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_luk(struct block_list *bl) -{ - int luk=0; - struct status_change *sc_data; - - nullpo_retr(0, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) { - luk=mob_db[((struct mob_data *)bl)->class].luk; - if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris] - luk+=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv; - } - else if(bl->type==BL_PC && (struct map_session_data *)bl) - luk=((struct map_session_data *)bl)->paramc[5]; - else if(bl->type==BL_PET && (struct pet_data *)bl) - luk=mob_db[((struct pet_data *)bl)->class].luk; - - if(sc_data) { - if(sc_data[SC_GLORIA].timer!=-1 && bl->type != BL_PC) // ƒOƒƒŠƒA(PC‚Ípc.c‚Å) - luk += 30; - if(sc_data[SC_CURSE].timer!=-1 ) // Žô‚¢ - luk=0; - if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // ƒgƒDƒ‹[ƒTƒCƒg - luk += 5; - } - if(luk < 0) luk = 0; - return luk; -} - -/*========================================== - * ‘ÎÛ‚ÌFlee‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å1ˆÈã - *------------------------------------------ - */ -int battle_get_flee(struct block_list *bl) -{ - int flee=1; - struct status_change *sc_data; - - nullpo_retr(1, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - flee=((struct map_session_data *)bl)->flee; - else - flee=battle_get_agi(bl) + battle_get_lv(bl); - - if(sc_data) { - if(sc_data[SC_WHISTLE].timer!=-1 && bl->type != BL_PC) - flee += flee*(sc_data[SC_WHISTLE].val1+sc_data[SC_WHISTLE].val2 - +(sc_data[SC_WHISTLE].val3>>16))/100; - if(sc_data[SC_BLIND].timer!=-1 && bl->type != BL_PC) - flee -= flee*25/100; - if(sc_data[SC_WINDWALK].timer!=-1 && bl->type != BL_PC) // ƒEƒBƒ“ƒhƒEƒH[ƒN - flee += flee*(sc_data[SC_WINDWALK].val2)/100; - if(sc_data[SC_SPIDERWEB].timer!=-1 && bl->type != BL_PC) //ƒXƒpƒCƒ_[ƒEƒFƒu - flee -= flee*50/100; - } - if(flee < 1) flee = 1; - return flee; -} -/*========================================== - * ‘ÎÛ‚ÌHit‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å1ˆÈã - *------------------------------------------ - */ -int battle_get_hit(struct block_list *bl) -{ - int hit=1; - struct status_change *sc_data; - - nullpo_retr(1, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - hit=((struct map_session_data *)bl)->hit; - else - hit=battle_get_dex(bl) + battle_get_lv(bl); - - if(sc_data) { - if(sc_data[SC_HUMMING].timer!=-1 && bl->type != BL_PC) // - hit += hit*(sc_data[SC_HUMMING].val1*2+sc_data[SC_HUMMING].val2 - +sc_data[SC_HUMMING].val3)/100; - if(sc_data[SC_BLIND].timer!=-1 && bl->type != BL_PC) // Žô‚¢ - hit -= hit*25/100; - if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // ƒgƒDƒ‹[ƒTƒCƒg - hit += 3*(sc_data[SC_TRUESIGHT].val1); - if(sc_data[SC_CONCENTRATION].timer!=-1 && bl->type != BL_PC) //ƒRƒ“ƒZƒ“ƒgƒŒ[ƒVƒ‡ƒ“ - hit += (hit*(10*(sc_data[SC_CONCENTRATION].val1)))/100; - } - if(hit < 1) hit = 1; - return hit; -} -/*========================================== - * ‘ÎÛ‚ÌŠ®‘S‰ñ”ð‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å1ˆÈã - *------------------------------------------ - */ -int battle_get_flee2(struct block_list *bl) -{ - int flee2=1; - struct status_change *sc_data; - - nullpo_retr(1, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_PC && (struct map_session_data *)bl){ - flee2 = battle_get_luk(bl) + 10; - flee2 += ((struct map_session_data *)bl)->flee2 - (((struct map_session_data *)bl)->paramc[5] + 10); - } - else - flee2=battle_get_luk(bl)+1; - - if(sc_data) { - if(sc_data[SC_WHISTLE].timer!=-1 && bl->type != BL_PC) - flee2 += (sc_data[SC_WHISTLE].val1+sc_data[SC_WHISTLE].val2 - +(sc_data[SC_WHISTLE].val3&0xffff))*10; - } - if(flee2 < 1) flee2 = 1; - return flee2; -} -/*========================================== - * ‘Îۂ̃NƒŠƒeƒBƒJƒ‹‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å1ˆÈã - *------------------------------------------ - */ -int battle_get_critical(struct block_list *bl) -{ - int critical=1; - struct status_change *sc_data; - - nullpo_retr(1, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_PC && (struct map_session_data *)bl){ - critical = battle_get_luk(bl)*3 + 10; - critical += ((struct map_session_data *)bl)->critical - ((((struct map_session_data *)bl)->paramc[5]*3) + 10); - } - else - critical=battle_get_luk(bl)*3 + 1; - - if(sc_data) { - if(sc_data[SC_FORTUNE].timer!=-1 && bl->type != BL_PC) - critical += (10+sc_data[SC_FORTUNE].val1+sc_data[SC_FORTUNE].val2 - +sc_data[SC_FORTUNE].val3)*10; - if(sc_data[SC_EXPLOSIONSPIRITS].timer!=-1 && bl->type != BL_PC) - critical += sc_data[SC_EXPLOSIONSPIRITS].val2; - if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) //ƒgƒDƒ‹[ƒTƒCƒg - critical += critical*sc_data[SC_TRUESIGHT].val1/100; - } - if(critical < 1) critical = 1; - return critical; -} -/*========================================== - * base_atk‚̎擾 - * –ß‚è‚Í®”‚Å1ˆÈã - *------------------------------------------ - */ -int battle_get_baseatk(struct block_list *bl) -{ - struct status_change *sc_data; - int batk=1; - - nullpo_retr(1, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - batk = ((struct map_session_data *)bl)->base_atk; //ݒ肳‚ê‚Ä‚¢‚ébase_atk - else { //‚»‚êˆÈŠO‚È‚ç - int str,dstr; - str = battle_get_str(bl); //STR - dstr = str/10; - batk = dstr*dstr + str; //base_atk‚ðŒvŽZ‚·‚é - } - if(sc_data) { //ó‘ÔˆÙí‚ ‚è - if(sc_data[SC_PROVOKE].timer!=-1 && bl->type != BL_PC) //PC‚Ńvƒƒ{ƒbƒN(SM_PROVOKE)ó‘Ô - batk = batk*(100+2*sc_data[SC_PROVOKE].val1)/100; //base_atk‘‰Á - if(sc_data[SC_CURSE].timer!=-1 ) //Žô‚í‚ê‚Ä‚¢‚½‚ç - batk -= batk*25/100; //base_atk‚ª25%Œ¸ - if(sc_data[SC_CONCENTRATION].timer!=-1 && bl->type != BL_PC) //ƒRƒ“ƒZƒ“ƒgƒŒ[ƒVƒ‡ƒ“ - batk += batk*(5*sc_data[SC_CONCENTRATION].val1)/100; - if(sc_data[SC_EDP].timer != -1) // [Celest] - batk += batk*(50+50*sc_data[SC_EDP].val1)/100; - } - if(batk < 1) batk = 1; //base_atk‚ÍÅ’á‚Å‚à1 - return batk; -} -/*========================================== - * ‘ÎÛ‚ÌAtk‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_atk(struct block_list *bl) -{ - struct status_change *sc_data; - int atk=0; - - nullpo_retr(0, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - atk = ((struct map_session_data*)bl)->watk; - else if(bl->type==BL_MOB && (struct mob_data *)bl) - atk = mob_db[((struct mob_data*)bl)->class].atk1; - else if(bl->type==BL_PET && (struct pet_data *)bl) - atk = mob_db[((struct pet_data*)bl)->class].atk1; - - if(sc_data) { - if(sc_data[SC_PROVOKE].timer!=-1 && bl->type != BL_PC) - atk = atk*(100+2*sc_data[SC_PROVOKE].val1)/100; - if(sc_data[SC_CURSE].timer!=-1 ) - atk -= atk*25/100; - if(sc_data[SC_CONCENTRATION].timer!=-1 && bl->type != BL_PC) //ƒRƒ“ƒZƒ“ƒgƒŒ[ƒVƒ‡ƒ“ - atk += atk*(5*sc_data[SC_CONCENTRATION].val1)/100; - } - if(atk < 0) atk = 0; - return atk; -} -/*========================================== - * ‘Îۂ̶ŽèAtk‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_atk_(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_PC && (struct map_session_data *)bl){ - int atk=((struct map_session_data*)bl)->watk_; - - if(((struct map_session_data *)bl)->sc_data[SC_CURSE].timer!=-1 ) - atk -= atk*25/100; - return atk; - } - else - return 0; -} -/*========================================== - * ‘ÎÛ‚ÌAtk2‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_atk2(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data*)bl)->watk2; - else { - struct status_change *sc_data=battle_get_sc_data(bl); - int atk2=0; - if(bl->type==BL_MOB && (struct mob_data *)bl) - atk2 = mob_db[((struct mob_data*)bl)->class].atk2; - else if(bl->type==BL_PET && (struct pet_data *)bl) - atk2 = mob_db[((struct pet_data*)bl)->class].atk2; - if(sc_data) { - if( sc_data[SC_IMPOSITIO].timer!=-1) - atk2 += sc_data[SC_IMPOSITIO].val1*5; - if( sc_data[SC_PROVOKE].timer!=-1 ) - atk2 = atk2*(100+2*sc_data[SC_PROVOKE].val1)/100; - if( sc_data[SC_CURSE].timer!=-1 ) - atk2 -= atk2*25/100; - if(sc_data[SC_DRUMBATTLE].timer!=-1) - atk2 += sc_data[SC_DRUMBATTLE].val2; - if(sc_data[SC_NIBELUNGEN].timer!=-1 && (battle_get_element(bl)/10) >= 8 ) - atk2 += sc_data[SC_NIBELUNGEN].val2; - if(sc_data[SC_STRIPWEAPON].timer!=-1) - atk2 = atk2*90/100; - if(sc_data[SC_CONCENTRATION].timer!=-1) //ƒRƒ“ƒZƒ“ƒgƒŒ[ƒVƒ‡ƒ“ - atk2 += atk2*(5*sc_data[SC_CONCENTRATION].val1)/100; - } - if(atk2 < 0) atk2 = 0; - return atk2; - } - return 0; -} -/*========================================== - * ‘Îۂ̶ŽèAtk2‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_atk_2(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data*)bl)->watk_2; - else - return 0; -} -/*========================================== - * ‘ÎÛ‚ÌMAtk1‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_matk1(struct block_list *bl) -{ - struct status_change *sc_data; - nullpo_retr(0, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_MOB){ - int matk,int_=battle_get_int(bl); - matk = int_+(int_/5)*(int_/5); - - if(sc_data) - if(sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC) - matk = matk*(100+2*sc_data[SC_MINDBREAKER].val1)/100; - return matk; - } - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data *)bl)->matk1; - else if(bl->type==BL_PET){ - int matk,int_=battle_get_int(bl); - matk = int_+(int_/5)*(int_/5); - - if(sc_data) - if(sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC) - matk = matk*(100+2*sc_data[SC_MINDBREAKER].val1)/100; - return matk; - } - else - return 0; -} -/*========================================== - * ‘ÎÛ‚ÌMAtk2‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_matk2(struct block_list *bl) -{ - struct status_change *sc_data=battle_get_sc_data(bl); - nullpo_retr(0, bl); - if(bl->type==BL_MOB){ - int matk,int_=battle_get_int(bl); - matk = int_+(int_/7)*(int_/7); - - if(sc_data) - if(sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC) - matk = matk*(100+2*sc_data[SC_MINDBREAKER].val1)/100; - return matk; - } - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data *)bl)->matk2; - else if(bl->type==BL_PET){ - int matk,int_=battle_get_int(bl); - matk = int_+(int_/7)*(int_/7); - if(sc_data) - if(sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC) - matk = matk*(100+2*sc_data[SC_MINDBREAKER].val1)/100; - return matk; - } - else - return 0; -} -/*========================================== - * ‘ÎÛ‚ÌDef‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_def(struct block_list *bl) -{ - struct status_change *sc_data; - int def=0,skilltimer=-1,skillid=0; - - nullpo_retr(0, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_PC && (struct map_session_data *)bl){ - def = ((struct map_session_data *)bl)->def; - skilltimer = ((struct map_session_data *)bl)->skilltimer; - skillid = ((struct map_session_data *)bl)->skillid; - } - else if(bl->type==BL_MOB && (struct mob_data *)bl) { - def = mob_db[((struct mob_data *)bl)->class].def; - skilltimer = ((struct mob_data *)bl)->skilltimer; - skillid = ((struct mob_data *)bl)->skillid; - } - else if(bl->type==BL_PET && (struct pet_data *)bl) - def = mob_db[((struct pet_data *)bl)->class].def; - - if(def < 1000000) { - if(sc_data) { - //ƒL[ƒsƒ“ƒOŽž‚ÍDEF100 - if( sc_data[SC_KEEPING].timer!=-1) - def = 100; - //ƒvƒƒ{ƒbƒNŽž‚ÍŒ¸ŽZ - if( sc_data[SC_PROVOKE].timer!=-1 && bl->type != BL_PC) - def = (def*(100 - 6*sc_data[SC_PROVOKE].val1)+50)/100; - //푾ŒÛ‚Ì‹¿‚«Žž‚͉ÁŽZ - if( sc_data[SC_DRUMBATTLE].timer!=-1 && bl->type != BL_PC) - def += sc_data[SC_DRUMBATTLE].val3; - //“łɂ©‚©‚Á‚Ä‚¢‚鎞‚ÍŒ¸ŽZ - if(sc_data[SC_POISON].timer!=-1 && bl->type != BL_PC) - def = def*75/100; - //ƒXƒgƒŠƒbƒvƒV[ƒ‹ƒhŽž‚ÍŒ¸ŽZ - if(sc_data[SC_STRIPSHIELD].timer!=-1 && bl->type != BL_PC) - def = def*85/100; - //ƒVƒOƒiƒ€ƒNƒ‹ƒVƒXŽž‚ÍŒ¸ŽZ - if(sc_data[SC_SIGNUMCRUCIS].timer!=-1 && bl->type != BL_PC) - def = def * (100 - sc_data[SC_SIGNUMCRUCIS].val2)/100; - //‰i‰“‚̬“׎ž‚ÍDEF0‚ɂȂé - if(sc_data[SC_ETERNALCHAOS].timer!=-1 && bl->type != BL_PC) - def = 0; - //“€Œ‹AΉ»Žž‚͉EƒVƒtƒg - if(sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)) - def >>= 1; - //ƒRƒ“ƒZƒ“ƒgƒŒ[ƒVƒ‡ƒ“Žž‚ÍŒ¸ŽZ - if( sc_data[SC_CONCENTRATION].timer!=-1 && bl->type != BL_PC) - def = (def*(100 - 5*sc_data[SC_CONCENTRATION].val1))/100; - } - //‰r¥’†‚͉r¥ŽžŒ¸ŽZ—¦‚ÉŠî‚¢‚ÄŒ¸ŽZ - if(skilltimer != -1) { - int def_rate = skill_get_castdef(skillid); - if(def_rate != 0) - def = (def * (100 - def_rate))/100; - } - } - if(def < 0) def = 0; - return def; -} -/*========================================== - * ‘ÎÛ‚ÌMDef‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_mdef(struct block_list *bl) -{ - struct status_change *sc_data; - int mdef=0; - - nullpo_retr(0, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - mdef = ((struct map_session_data *)bl)->mdef; - else if(bl->type==BL_MOB && (struct mob_data *)bl) - mdef = mob_db[((struct mob_data *)bl)->class].mdef; - else if(bl->type==BL_PET && (struct pet_data *)bl) - mdef = mob_db[((struct pet_data *)bl)->class].mdef; - - if(mdef < 1000000) { - if(sc_data) { - //ƒoƒŠƒA[ó‘ÔŽž‚ÍMDEF100 - if(sc_data[SC_BARRIER].timer != -1) - mdef = 100; - //“€Œ‹AΉ»Žž‚Í1.25”{ - if(sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)) - mdef = mdef*125/100; - if( sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC) - mdef -= (mdef*6*sc_data[SC_MINDBREAKER].val1)/100; - } - } - if(mdef < 0) mdef = 0; - return mdef; -} -/*========================================== - * ‘ÎÛ‚ÌDef2‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å1ˆÈã - *------------------------------------------ - */ -int battle_get_def2(struct block_list *bl) -{ - struct status_change *sc_data; - int def2=1; - - nullpo_retr(1, bl); - sc_data=battle_get_sc_data(bl); - if(bl->type==BL_PC) - def2 = ((struct map_session_data *)bl)->def2; - else if(bl->type==BL_MOB) - def2 = mob_db[((struct mob_data *)bl)->class].vit; - else if(bl->type==BL_PET) - def2 = mob_db[((struct pet_data *)bl)->class].vit; - - if(sc_data) { - if( sc_data[SC_ANGELUS].timer!=-1 && bl->type != BL_PC) - def2 = def2*(110+5*sc_data[SC_ANGELUS].val1)/100; - if( sc_data[SC_PROVOKE].timer!=-1 && bl->type != BL_PC) - def2 = (def2*(100 - 6*sc_data[SC_PROVOKE].val1)+50)/100; - if(sc_data[SC_POISON].timer!=-1 && bl->type != BL_PC) - def2 = def2*75/100; - //ƒRƒ“ƒZƒ“ƒgƒŒ[ƒVƒ‡ƒ“Žž‚ÍŒ¸ŽZ - if( sc_data[SC_CONCENTRATION].timer!=-1 && bl->type != BL_PC) - def2 = def2*(100 - 5*sc_data[SC_CONCENTRATION].val1)/100; - } - if(def2 < 1) def2 = 1; - return def2; -} -/*========================================== - * ‘ÎÛ‚ÌMDef2‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å0ˆÈã - *------------------------------------------ - */ -int battle_get_mdef2(struct block_list *bl) -{ - int mdef2=0; - struct status_change *sc_data=battle_get_sc_data(bl); - - nullpo_retr(0, bl); - if(bl->type==BL_MOB) - mdef2 = mob_db[((struct mob_data *)bl)->class].int_ + (mob_db[((struct mob_data *)bl)->class].vit>>1); - else if(bl->type==BL_PC) - mdef2 = ((struct map_session_data *)bl)->mdef2 + (((struct map_session_data *)bl)->paramc[2]>>1); - else if(bl->type==BL_PET) - mdef2 = mob_db[((struct pet_data *)bl)->class].int_ + (mob_db[((struct pet_data *)bl)->class].vit>>1); - if(sc_data) { - if( sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC) - mdef2 -= (mdef2*6*sc_data[SC_MINDBREAKER].val1)/100; - } - if(mdef2 < 0) mdef2 = 0; - return mdef2; -} -/*========================================== - * ‘ÎÛ‚ÌSpeed(ˆÚ“®‘¬“x)‚ð•Ô‚·(”Ä—p) - * –ß‚è‚Í®”‚Å1ˆÈã - * Speed‚ͬ‚³‚¢‚Ù‚¤‚ªˆÚ“®‘¬“x‚ª‘¬‚¢ - *------------------------------------------ - */ -int battle_get_speed(struct block_list *bl) -{ - nullpo_retr(1000, bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data *)bl)->speed; - else { - struct status_change *sc_data=battle_get_sc_data(bl); - int speed = 1000; - if(bl->type==BL_MOB && (struct mob_data *)bl) { - speed = ((struct mob_data *)bl)->speed; - if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris] - speed-=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv; - } - else if(bl->type==BL_PET && (struct pet_data *)bl) - speed = ((struct pet_data *)bl)->msd->petDB->speed; - - if(sc_data) { - //‘¬“x‘‰ÁŽž‚Í25%Œ¸ŽZ - if(sc_data[SC_INCREASEAGI].timer!=-1 && sc_data[SC_DONTFORGETME].timer == -1) - speed -= speed*25/100; - //‘¬“xŒ¸Žž‚Í25%‰ÁŽZ - if(sc_data[SC_DECREASEAGI].timer!=-1) - speed = speed*125/100; - //ƒNƒ@ƒOƒ}ƒCƒAŽž‚Í50%‰ÁŽZ - if(sc_data[SC_QUAGMIRE].timer!=-1) - speed = speed*3/2; - //Ž„‚ð–Y‚ê‚È‚¢‚ÅcŽž‚͉ÁŽZ - if(sc_data[SC_DONTFORGETME].timer!=-1) - speed = speed*(100+sc_data[SC_DONTFORGETME].val1*2 + sc_data[SC_DONTFORGETME].val2 + (sc_data[SC_DONTFORGETME].val3&0xffff))/100; - //‹à„Žž‚Í25%‰ÁŽZ - if(sc_data[SC_STEELBODY].timer!=-1) - speed = speed*125/100; - //ƒfƒBƒtƒFƒ“ƒ_[Žž‚͉ÁŽZ - if(sc_data[SC_DEFENDER].timer!=-1) - speed = (speed * (155 - sc_data[SC_DEFENDER].val1*5)) / 100; - //—x‚èó‘Ô‚Í4”{’x‚¢ - if(sc_data[SC_DANCING].timer!=-1 ) - speed*=4; - //Žô‚¢Žž‚Í450‰ÁŽZ - if(sc_data[SC_CURSE].timer!=-1) - speed = speed + 450; - //ƒEƒBƒ“ƒhƒEƒH[ƒNŽž‚ÍLv*2%Œ¸ŽZ - if(sc_data[SC_WINDWALK].timer!=-1) - speed -= (speed*(sc_data[SC_WINDWALK].val1*2))/100; - if(sc_data[SC_SLOWDOWN].timer!=-1) - speed = speed*150/100; - } - if(speed < 1) speed = 1; - return speed; - } - - return 1000; -} -/*========================================== - * ‘ÎÛ‚ÌaDelay(UŒ‚ŽžƒfƒBƒŒƒC)‚ð•Ô‚·(”Ä—p) - * aDelay‚ͬ‚³‚¢‚Ù‚¤‚ªUŒ‚‘¬“x‚ª‘¬‚¢ - *------------------------------------------ - */ -int battle_get_adelay(struct block_list *bl) -{ - nullpo_retr(4000, bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - return (((struct map_session_data *)bl)->aspd<<1); - else { - struct status_change *sc_data=battle_get_sc_data(bl); - int adelay=4000,aspd_rate = 100,i; - if(bl->type==BL_MOB && (struct mob_data *)bl) - adelay = mob_db[((struct mob_data *)bl)->class].adelay; - else if(bl->type==BL_PET && (struct pet_data *)bl) - adelay = mob_db[((struct pet_data *)bl)->class].adelay; - - if(sc_data) { - //ƒc[ƒnƒ“ƒhƒNƒCƒbƒPƒ“Žg—pŽž‚ŃNƒ@ƒOƒ}ƒCƒA‚Å‚àŽ„‚ð–Y‚ê‚È‚¢‚Åc‚Å‚à‚È‚¢Žž‚Í3Š„Œ¸ŽZ - if(sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ - aspd_rate -= 30; - //ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ…Žg—pŽž‚Ńc[ƒnƒ“ƒhƒNƒCƒbƒPƒ“‚Å‚àƒNƒ@ƒOƒ}ƒCƒA‚Å‚àŽ„‚ð–Y‚ê‚È‚¢‚Åc‚Å‚à‚È‚¢Žž‚Í - if(sc_data[SC_ADRENALINE].timer != -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 && - sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) { // ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… - //Žg—pŽÒ‚ƃp[ƒeƒBƒƒ“ƒo[‚ÅŠi·‚ªo‚éÝ’è‚łȂ¯‚ê‚Î3Š„Œ¸ŽZ - if(sc_data[SC_ADRENALINE].val2 || !battle_config.party_skill_penaly) - aspd_rate -= 30; - //‚»‚¤‚łȂ¯‚ê‚Î2.5Š„Œ¸ŽZ - else - aspd_rate -= 25; - } - //ƒXƒsƒAƒNƒBƒbƒPƒ“Žž‚ÍŒ¸ŽZ - if(sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 && - sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // ƒXƒsƒAƒNƒBƒbƒPƒ“ - aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2; - //—[“ú‚̃AƒTƒVƒ“ƒNƒƒXŽž‚ÍŒ¸ŽZ - if(sc_data[SC_ASSNCROS].timer!=-1 && // —[—z‚̃AƒTƒVƒ“ƒNƒƒX - sc_data[SC_TWOHANDQUICKEN].timer==-1 && sc_data[SC_ADRENALINE].timer==-1 && sc_data[SC_SPEARSQUICKEN].timer==-1 && - sc_data[SC_DONTFORGETME].timer == -1) - aspd_rate -= 5+sc_data[SC_ASSNCROS].val1+sc_data[SC_ASSNCROS].val2+sc_data[SC_ASSNCROS].val3; - //Ž„‚ð–Y‚ê‚È‚¢‚ÅcŽž‚͉ÁŽZ - if(sc_data[SC_DONTFORGETME].timer!=-1) // Ž„‚ð–Y‚ê‚È‚¢‚Å - aspd_rate += sc_data[SC_DONTFORGETME].val1*3 + sc_data[SC_DONTFORGETME].val2 + (sc_data[SC_DONTFORGETME].val3>>16); - //‹à„Žž25%‰ÁŽZ - if(sc_data[SC_STEELBODY].timer!=-1) // ‹à„ - aspd_rate += 25; - //‘‘¬ƒ|[ƒVƒ‡ƒ“Žg—pŽž‚ÍŒ¸ŽZ - if( sc_data[i=SC_SPEEDPOTION2].timer!=-1 || sc_data[i=SC_SPEEDPOTION1].timer!=-1 || sc_data[i=SC_SPEEDPOTION0].timer!=-1) - aspd_rate -= sc_data[i].val2; - //ƒfƒBƒtƒFƒ“ƒ_[Žž‚͉ÁŽZ - if(sc_data[SC_DEFENDER].timer != -1) - adelay += (1100 - sc_data[SC_DEFENDER].val1*100); - } - if(aspd_rate != 100) - adelay = adelay*aspd_rate/100; - if(adelay < battle_config.monster_max_aspd<<1) adelay = battle_config.monster_max_aspd<<1; - return adelay; - } - return 4000; -} -int battle_get_amotion(struct block_list *bl) -{ - nullpo_retr(2000, bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data *)bl)->amotion; - else { - struct status_change *sc_data=battle_get_sc_data(bl); - int amotion=2000,aspd_rate = 100,i; - if(bl->type==BL_MOB && (struct mob_data *)bl) - amotion = mob_db[((struct mob_data *)bl)->class].amotion; - else if(bl->type==BL_PET && (struct pet_data *)bl) - amotion = mob_db[((struct pet_data *)bl)->class].amotion; - - if(sc_data) { - if(sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ - aspd_rate -= 30; - if(sc_data[SC_ADRENALINE].timer != -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 && - sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) { // ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… - if(sc_data[SC_ADRENALINE].val2 || !battle_config.party_skill_penaly) - aspd_rate -= 30; - else - aspd_rate -= 25; - } - if(sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 && - sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // ƒXƒsƒAƒNƒBƒbƒPƒ“ - aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2; - if(sc_data[SC_ASSNCROS].timer!=-1 && // —[—z‚̃AƒTƒVƒ“ƒNƒƒX - sc_data[SC_TWOHANDQUICKEN].timer==-1 && sc_data[SC_ADRENALINE].timer==-1 && sc_data[SC_SPEARSQUICKEN].timer==-1 && - sc_data[SC_DONTFORGETME].timer == -1) - aspd_rate -= 5+sc_data[SC_ASSNCROS].val1+sc_data[SC_ASSNCROS].val2+sc_data[SC_ASSNCROS].val3; - if(sc_data[SC_DONTFORGETME].timer!=-1) // Ž„‚ð–Y‚ê‚È‚¢‚Å - aspd_rate += sc_data[SC_DONTFORGETME].val1*3 + sc_data[SC_DONTFORGETME].val2 + (sc_data[SC_DONTFORGETME].val3>>16); - if(sc_data[SC_STEELBODY].timer!=-1) // ‹à„ - aspd_rate += 25; - if( sc_data[i=SC_SPEEDPOTION2].timer!=-1 || sc_data[i=SC_SPEEDPOTION1].timer!=-1 || sc_data[i=SC_SPEEDPOTION0].timer!=-1) - aspd_rate -= sc_data[i].val2; - if(sc_data[SC_DEFENDER].timer != -1) - amotion += (550 - sc_data[SC_DEFENDER].val1*50); - } - if(aspd_rate != 100) - amotion = amotion*aspd_rate/100; - if(amotion < battle_config.monster_max_aspd) amotion = battle_config.monster_max_aspd; - return amotion; - } - return 2000; -} -int battle_get_dmotion(struct block_list *bl) -{ - int ret; - struct status_change *sc_data; - - nullpo_retr(0, bl); - sc_data = battle_get_sc_data(bl); - if(bl->type==BL_MOB && (struct mob_data *)bl){ - ret=mob_db[((struct mob_data *)bl)->class].dmotion; - if(battle_config.monster_damage_delay_rate != 100) - ret = ret*battle_config.monster_damage_delay_rate/400; - } - else if(bl->type==BL_PC && (struct map_session_data *)bl){ - ret=((struct map_session_data *)bl)->dmotion; - if(battle_config.pc_damage_delay_rate != 100) - ret = ret*battle_config.pc_damage_delay_rate/400; - } - else if(bl->type==BL_PET && (struct pet_data *)bl) - ret=mob_db[((struct pet_data *)bl)->class].dmotion; - else - return 2000; - - if((sc_data && (sc_data[SC_ENDURE].timer!=-1 || sc_data[SC_BERSERK].timer!=-1)) || - (bl->type == BL_PC && ((struct map_session_data *)bl)->special_state.infinite_endure)) - ret=0; - - return ret; -} -int battle_get_element(struct block_list *bl) -{ - int ret = 20; - struct status_change *sc_data; - - nullpo_retr(ret, bl); - sc_data = battle_get_sc_data(bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) // 10‚̈ÊLv*2A‚P‚̈ʑ®« - ret=((struct mob_data *)bl)->def_ele; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - ret=20+((struct map_session_data *)bl)->def_ele; // –hŒä‘®«Lv1 - else if(bl->type==BL_PET && (struct pet_data *)bl) - ret = mob_db[((struct pet_data *)bl)->class].element; - - if(sc_data) { - if( sc_data[SC_BENEDICTIO].timer!=-1 ) // ¹‘Ì~•Ÿ - ret=26; - if( sc_data[SC_FREEZE].timer!=-1 ) // “€Œ‹ - ret=21; - if( sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0) - ret=22; - } - - return ret; -} -int battle_get_attack_element(struct block_list *bl) -{ - int ret = 0; - struct status_change *sc_data=battle_get_sc_data(bl); - - nullpo_retr(0, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - ret=0; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - ret=((struct map_session_data *)bl)->atk_ele; - else if(bl->type==BL_PET && (struct pet_data *)bl) - ret=0; - - if(sc_data) { - if( sc_data[SC_FROSTWEAPON].timer!=-1) // ƒtƒƒXƒgƒEƒFƒ|ƒ“ - ret=1; - if( sc_data[SC_SEISMICWEAPON].timer!=-1) // ƒTƒCƒYƒ~ƒbƒNƒEƒFƒ|ƒ“ - ret=2; - if( sc_data[SC_FLAMELAUNCHER].timer!=-1) // ƒtƒŒ[ƒ€ƒ‰ƒ“ƒ`ƒƒ[ - ret=3; - if( sc_data[SC_LIGHTNINGLOADER].timer!=-1) // ƒ‰ƒCƒgƒjƒ“ƒOƒ[ƒ_[ - ret=4; - if( sc_data[SC_ENCPOISON].timer!=-1) // ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“ - ret=5; - if( sc_data[SC_ASPERSIO].timer!=-1) // ƒAƒXƒyƒ‹ƒVƒI - ret=6; - } - - return ret; -} -int battle_get_attack_element2(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) { - int ret = ((struct map_session_data *)bl)->atk_ele_; - struct status_change *sc_data = ((struct map_session_data *)bl)->sc_data; - - if(sc_data) { - if( sc_data[SC_FROSTWEAPON].timer!=-1) // ƒtƒƒXƒgƒEƒFƒ|ƒ“ - ret=1; - if( sc_data[SC_SEISMICWEAPON].timer!=-1) // ƒTƒCƒYƒ~ƒbƒNƒEƒFƒ|ƒ“ - ret=2; - if( sc_data[SC_FLAMELAUNCHER].timer!=-1) // ƒtƒŒ[ƒ€ƒ‰ƒ“ƒ`ƒƒ[ - ret=3; - if( sc_data[SC_LIGHTNINGLOADER].timer!=-1) // ƒ‰ƒCƒgƒjƒ“ƒOƒ[ƒ_[ - ret=4; - if( sc_data[SC_ENCPOISON].timer!=-1) // ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“ - ret=5; - if( sc_data[SC_ASPERSIO].timer!=-1) // ƒAƒXƒyƒ‹ƒVƒI - ret=6; - } - return ret; - } - return 0; -} -int battle_get_party_id(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data *)bl)->status.party_id; - else if(bl->type==BL_MOB && (struct mob_data *)bl){ - struct mob_data *md=(struct mob_data *)bl; - if( md->master_id>0 ) - return -md->master_id; - return -md->bl.id; - } - else if(bl->type==BL_SKILL && (struct skill_unit *)bl) - return ((struct skill_unit *)bl)->group->party_id; - else - return 0; -} -int battle_get_guild_id(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data *)bl)->status.guild_id; - else if(bl->type==BL_MOB && (struct mob_data *)bl) - return ((struct mob_data *)bl)->class; - else if(bl->type==BL_SKILL && (struct skill_unit *)bl) - return ((struct skill_unit *)bl)->group->guild_id; - else - return 0; -} -int battle_get_race(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return mob_db[((struct mob_data *)bl)->class].race; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return 7; - else if(bl->type==BL_PET && (struct pet_data *)bl) - return mob_db[((struct pet_data *)bl)->class].race; - else - return 0; -} -int battle_get_size(struct block_list *bl) -{ - nullpo_retr(1, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return mob_db[((struct mob_data *)bl)->class].size; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return 1; - else if(bl->type==BL_PET && (struct pet_data *)bl) - return mob_db[((struct pet_data *)bl)->class].size; - else - return 1; -} -int battle_get_mode(struct block_list *bl) -{ - nullpo_retr(0x01, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return mob_db[((struct mob_data *)bl)->class].mode; - else if(bl->type==BL_PET && (struct pet_data *)bl) - return mob_db[((struct pet_data *)bl)->class].mode; - else - return 0x01; // ‚Æ‚è‚ ‚¦‚¸“®‚‚Æ‚¢‚¤‚±‚Æ‚Å1 -} - -int battle_get_mexp(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return mob_db[((struct mob_data *)bl)->class].mexp; - else if(bl->type==BL_PET && (struct pet_data *)bl) - return mob_db[((struct pet_data *)bl)->class].mexp; - else - return 0; -} - -// StatusChangeŒn‚ÌŠ“¾ -struct status_change *battle_get_sc_data(struct block_list *bl) -{ - nullpo_retr(NULL, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return ((struct mob_data*)bl)->sc_data; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data*)bl)->sc_data; - return NULL; -} -short *battle_get_sc_count(struct block_list *bl) -{ - nullpo_retr(NULL, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return &((struct mob_data*)bl)->sc_count; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return &((struct map_session_data*)bl)->sc_count; - return NULL; -} -short *battle_get_opt1(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return &((struct mob_data*)bl)->opt1; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return &((struct map_session_data*)bl)->opt1; - else if(bl->type==BL_NPC && (struct npc_data *)bl) - return &((struct npc_data*)bl)->opt1; - return 0; -} -short *battle_get_opt2(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return &((struct mob_data*)bl)->opt2; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return &((struct map_session_data*)bl)->opt2; - else if(bl->type==BL_NPC && (struct npc_data *)bl) - return &((struct npc_data*)bl)->opt2; - return 0; -} -short *battle_get_opt3(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return &((struct mob_data*)bl)->opt3; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return &((struct map_session_data*)bl)->opt3; - else if(bl->type==BL_NPC && (struct npc_data *)bl) - return &((struct npc_data*)bl)->opt3; - return 0; -} -short *battle_get_option(struct block_list *bl) -{ - nullpo_retr(0, bl); - if(bl->type==BL_MOB && (struct mob_data *)bl) - return &((struct mob_data*)bl)->option; - else if(bl->type==BL_PC && (struct map_session_data *)bl) - return &((struct map_session_data*)bl)->status.option; - else if(bl->type==BL_NPC && (struct npc_data *)bl) - return &((struct npc_data*)bl)->option; - return 0; -} - -//------------------------------------------------------------------- // ƒ_ƒ[ƒW‚Ì’x‰„ struct battle_delay_damage_ { - struct block_list *src,*target; + struct block_list *src; + int target; int damage; int flag; }; int battle_delay_damage_sub(int tid,unsigned int tick,int id,int data) { struct battle_delay_damage_ *dat=(struct battle_delay_damage_ *)data; - if( dat && map_id2bl(id)==dat->src && dat->target->prev!=NULL) - battle_damage(dat->src,dat->target,dat->damage,dat->flag); - free(dat); + struct block_list *target=map_id2bl(dat->target); + if( dat && map_id2bl(id)==dat->src && target && target->prev!=NULL) + battle_damage(dat->src,target,dat->damage,dat->flag); + aFree(dat); return 0; } int battle_delay_damage(unsigned int tick,struct block_list *src,struct block_list *target,int damage,int flag) @@ -1319,7 +82,7 @@ int battle_delay_damage(unsigned int tick,struct block_list *src,struct block_li dat->src=src; - dat->target=target; + dat->target=target->id; dat->damage=damage; dat->flag=flag; add_timer(tick,battle_delay_damage_sub,src->id,(int)dat); @@ -1330,7 +93,7 @@ int battle_delay_damage(unsigned int tick,struct block_list *src,struct block_li int battle_damage(struct block_list *bl,struct block_list *target,int damage,int flag) { struct map_session_data *sd=NULL; - struct status_change *sc_data=battle_get_sc_data(target); + struct status_change *sc_data=status_get_sc_data(target); short *sc_count; int i; @@ -1353,14 +116,14 @@ int battle_damage(struct block_list *bl,struct block_list *target,int damage,int if(damage<0) return battle_heal(bl,target,-damage,0,flag); - if(!flag && (sc_count=battle_get_sc_count(target))!=NULL && *sc_count>0){ + if(!flag && (sc_count=status_get_sc_count(target))!=NULL && *sc_count>0){ // “€Œ‹AΉ»A‡–°‚ðÁ‹Ž if(sc_data[SC_FREEZE].timer!=-1) - skill_status_change_end(target,SC_FREEZE,-1); + status_change_end(target,SC_FREEZE,-1); if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0) - skill_status_change_end(target,SC_STONE,-1); + status_change_end(target,SC_STONE,-1); if(sc_data[SC_SLEEP].timer!=-1) - skill_status_change_end(target,SC_SLEEP,-1); + status_change_end(target,SC_SLEEP,-1); } if(target->type==BL_MOB){ // MOB @@ -1479,29 +242,35 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i struct mob_data *md=NULL; struct status_change *sc_data,*sc; short *sc_count; - int class; + int class_; nullpo_retr(0, bl); - class = battle_get_class(bl); + class_ = status_get_class(bl); if(bl->type==BL_MOB) md=(struct mob_data *)bl; else sd=(struct map_session_data *)bl; - sc_data=battle_get_sc_data(bl); - sc_count=battle_get_sc_count(bl); + sc_data=status_get_sc_data(bl); + sc_count=status_get_sc_count(bl); if(sc_count!=NULL && *sc_count>0){ - - if(sc_data[SC_SAFETYWALL].timer!=-1 && damage>0 && flag&BF_WEAPON && flag&BF_SHORT && skill_num != NPC_GUIDEDATTACK){ + if (sc_data[SC_SAFETYWALL].timer!=-1 && damage>0 && flag&BF_WEAPON && + flag&BF_SHORT && skill_num != NPC_GUIDEDATTACK) { // ƒZ[ƒtƒeƒBƒEƒH[ƒ‹ - struct skill_unit *unit=(struct skill_unit*)sc_data[SC_SAFETYWALL].val2; - if( unit && unit->alive && (--unit->group->val2)<=0 ) - skill_delunit(unit); - skill_unit_move(bl,gettick(),1); // d‚ËŠ|‚¯ƒ`ƒFƒbƒN - damage=0; + struct skill_unit *unit; + unit = (struct skill_unit *)sc_data[SC_SAFETYWALL].val2; + if (unit) { + if (unit->group && (--unit->group->val2)<=0) + skill_delunit(unit); + damage=0; + } else { + status_change_end(bl,SC_SAFETYWALL,-1); + } } - if(sc_data[SC_PNEUMA].timer!=-1 && damage>0 && ((flag&BF_WEAPON && flag&BF_LONG && skill_num != NPC_GUIDEDATTACK) || - (flag&BF_MISC && (skill_num == HT_BLITZBEAT || skill_num == SN_FALCONASSAULT)))){ // [DracoRPG] + if(sc_data[SC_PNEUMA].timer!=-1 && damage>0 && + ((flag&BF_WEAPON && flag&BF_LONG && skill_num != NPC_GUIDEDATTACK) || + (flag&BF_MISC && (skill_num == HT_BLITZBEAT || skill_num == SN_FALCONASSAULT)) || + (flag&BF_MAGIC && skill_num == ASC_BREAKER))){ // [DracoRPG] // ƒjƒ…[ƒ} damage=0; } @@ -1514,29 +283,35 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i if(sc_data[SC_AETERNA].timer!=-1 && damage>0){ // ƒŒƒbƒNƒXƒG[ƒeƒ‹ƒi damage<<=1; - skill_status_change_end( bl,SC_AETERNA,-1 ); + status_change_end( bl,SC_AETERNA,-1 ); } //‘®«ê‚̃_ƒ[ƒW‘‰Á if(sc_data[SC_VOLCANO].timer!=-1){ // ƒ{ƒ‹ƒP[ƒm if(flag&BF_SKILL && skill_get_pl(skill_num)==3) - damage += damage*sc_data[SC_VOLCANO].val4/100; - else if(!flag&BF_SKILL && battle_get_attack_element(bl)==3) - damage += damage*sc_data[SC_VOLCANO].val4/100; + //damage += damage*sc_data[SC_VOLCANO].val4/100; + damage += damage * enchant_eff[sc_data[SC_VOLCANO].val1-1] /100; + else if(!flag&BF_SKILL && status_get_attack_element(bl)==3) + //damage += damage*sc_data[SC_VOLCANO].val4/100; + damage += damage * enchant_eff[sc_data[SC_VOLCANO].val1-1] /100; } if(sc_data[SC_VIOLENTGALE].timer!=-1){ // ƒoƒCƒIƒŒƒ“ƒgƒQƒCƒ‹ if(flag&BF_SKILL && skill_get_pl(skill_num)==4) - damage += damage*sc_data[SC_VIOLENTGALE].val4/100; - else if(!flag&BF_SKILL && battle_get_attack_element(bl)==4) - damage += damage*sc_data[SC_VIOLENTGALE].val4/100; + //damage += damage*sc_data[SC_VIOLENTGALE].val4/100; + damage += damage * enchant_eff[sc_data[SC_VIOLENTGALE].val1-1] /100; + else if(!flag&BF_SKILL && status_get_attack_element(bl)==4) + //damage += damage*sc_data[SC_VIOLENTGALE].val4/100; + damage += damage * enchant_eff[sc_data[SC_VIOLENTGALE].val1-1] /100; } if(sc_data[SC_DELUGE].timer!=-1){ // ƒfƒŠƒ…[ƒW if(flag&BF_SKILL && skill_get_pl(skill_num)==1) - damage += damage*sc_data[SC_DELUGE].val4/100; - else if(!flag&BF_SKILL && battle_get_attack_element(bl)==1) - damage += damage*sc_data[SC_DELUGE].val4/100; + //damage += damage*sc_data[SC_DELUGE].val4/100; + damage += damage * enchant_eff[sc_data[SC_DELUGE].val1-1] /100; + else if(!flag&BF_SKILL && status_get_attack_element(bl)==1) + //damage += damage*sc_data[SC_DELUGE].val4/100; + damage += damage * enchant_eff[sc_data[SC_DELUGE].val1-1] /100; } if(sc_data[SC_ENERGYCOAT].timer!=-1 && damage>0 && flag&BF_WEAPON){ // ƒGƒiƒW[ƒR[ƒg @@ -1549,7 +324,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i clif_updatestatus(sd,SP_SP); } if(sd->status.sp<=0) - skill_status_change_end( bl,SC_ENERGYCOAT,-1 ); + status_change_end( bl,SC_ENERGYCOAT,-1 ); } else damage -= damage * (sc_data[SC_ENERGYCOAT].val1 * 6) / 100; @@ -1563,7 +338,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i else damage=-sc->val2; } if((--sc->val3)<=0 || (sc->val2<=0) || skill_num == AL_HOLYLIGHT) - skill_status_change_end(bl, SC_KYRIE, -1); + status_change_end(bl, SC_KYRIE, -1); } if(sc_data[SC_BASILICA].timer!=-1 && damage > 0){ @@ -1577,12 +352,21 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i if(sc_data[SC_AUTOGUARD].timer != -1 && damage > 0 && flag&BF_WEAPON) { if(rand()%100 < sc_data[SC_AUTOGUARD].val2) { + int delay; + damage = 0; clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sc_data[SC_AUTOGUARD].val1,1); + // different delay depending on skill level [celest] + if (sc_data[SC_AUTOGUARD].val1 <= 5) + delay = 300; + else if (sc_data[SC_AUTOGUARD].val1 > 5 && sc_data[SC_AUTOGUARD].val1 <= 9) + delay = 200; + else + delay = 100; if(sd) - sd->canmove_tick = gettick() + 300; + sd->canmove_tick = gettick() + delay; else if(md) - md->canmove_tick = gettick() + 300; + md->canmove_tick = gettick() + delay; } } // -- moonsoul (chance to block attacks with new Lord Knight skill parrying) @@ -1595,39 +379,43 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i } // ƒŠƒWƒFƒNƒgƒ\[ƒh if(sc_data[SC_REJECTSWORD].timer!=-1 && damage > 0 && flag&BF_WEAPON && - ((src->type==BL_PC && ((struct map_session_data *)src)->status.weapon == (1 || 2 || 3)) || src->type==BL_MOB )){ + // Fixed the condition check [Aalye] + (src->type==BL_MOB || (src->type==BL_PC && (((struct map_session_data *)src)->status.weapon == 1 || + ((struct map_session_data *)src)->status.weapon == 2 || + ((struct map_session_data *)src)->status.weapon == 3)))){ if(rand()%100 < (15*sc_data[SC_REJECTSWORD].val1)){ //”½ŽËŠm—¦‚Í15*Lv damage = damage*50/100; + clif_damage(bl,src,gettick(),0,0,damage,0,0,0); battle_damage(bl,src,damage,0); //ƒ_ƒ[ƒW‚ð—^‚¦‚½‚̂͗ǂ¢‚ñ‚¾‚ªA‚±‚±‚©‚ç‚Ç‚¤‚µ‚Ä•\ަ‚·‚é‚ñ‚¾‚©‚í‚©‚ñ‚Ë‚¥ //ƒGƒtƒFƒNƒg‚à‚±‚ê‚Å‚¢‚¢‚Ì‚©‚í‚©‚ñ‚Ë‚¥ clif_skill_nodamage(bl,bl,ST_REJECTSWORD,sc_data[SC_REJECTSWORD].val1,1); if((--sc_data[SC_REJECTSWORD].val2)<=0) - skill_status_change_end(bl, SC_REJECTSWORD, -1); + status_change_end(bl, SC_REJECTSWORD, -1); } } if(sc_data[SC_SPIDERWEB].timer!=-1 && damage > 0) // [Celest] if ((flag&BF_SKILL && skill_get_pl(skill_num)==3) || - (!flag&BF_SKILL && battle_get_attack_element(src)==3)) { + (!flag&BF_SKILL && status_get_attack_element(src)==3)) { damage<<=1; - skill_status_change_end(bl, SC_SPIDERWEB, -1); + status_change_end(bl, SC_SPIDERWEB, -1); } - + if(sc_data[SC_FOGWALL].timer != -1 && flag&BF_MAGIC) - if(rand()%100 < sc_data[SC_FOGWALL].val2) + if(rand()%100 < 75) damage = 0; } - if(class == 1288 || class == 1287 || class == 1286 || class == 1285) { -// if(class == 1288) { - if(class == 1288 && flag&BF_SKILL) + if(class_ == 1288 || class_ == 1287 || class_ == 1286 || class_ == 1285) { +// if(class_ == 1288) { + if(class_ == 1288 && (flag&BF_SKILL || skill_num == ASC_BREAKER || skill_num == PA_SACRIFICE)) damage=0; if(src->type == BL_PC) { struct guild *g=guild_search(((struct map_session_data *)src)->status.guild_id); struct guild_castle *gc=guild_mapname2gc(map[bl->m].name); if(!((struct map_session_data *)src)->status.guild_id) damage=0; - if(gc && agit_flag==0 && class != 1288) // guardians cannot be damaged during non-woe [Valaris] + if(gc && agit_flag==0 && class_ != 1288) // guardians cannot be damaged during non-woe [Valaris] damage=0; // end woe check [Valaris] if(g == NULL) damage=0;//ƒMƒ‹ƒh–¢‰Á“ü‚È‚çƒ_ƒ[ƒW–³‚µ @@ -1636,12 +424,18 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i else if(g && guild_checkskill(g,GD_APPROVAL) <= 0) damage=0;//³‹KƒMƒ‹ƒh³”F‚ª‚È‚¢‚ƃ_ƒ[ƒW–³‚µ else if (battle_config.guild_max_castles != 0 && guild_checkcastles(g)>=battle_config.guild_max_castles) - damage = 0; // [MouseJstr] + damage = 0; // [MouseJstr] + else if (g && gc && guild_check_alliance(gc->guild_id, g->guild_id, 0) == 1) + return 0; } else damage = 0; } if(map[bl->m].flag.gvg && damage > 0) { //GvG + if(bl->type == BL_MOB){ //defense‚ª‚ ‚ê‚΃_ƒ[ƒW‚ªŒ¸‚é‚炵‚¢H + struct guild_castle *gc=guild_mapname2gc(map[bl->m].name); + if (gc) damage -= damage*(gc->defense/100)*(battle_config.castle_defense_rate/100); + } if(flag&BF_WEAPON) { if(flag&BF_SHORT) damage=damage*battle_config.gvg_short_damage_rate/100; @@ -1671,20 +465,47 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i } /*========================================== + * HP/SP‹zŽû‚ÌŒvŽZ + *------------------------------------------ + */ +int battle_calc_drain(int damage, int rate, int per, int val) +{ + int diff = 0; + + if (damage <= 0 || rate <= 0) + return 0; + + if (per && rand()%100 < rate) { + diff = (damage * per) / 100; + if (diff == 0) { + if (per > 0) + diff = 1; + else + diff = -1; + } + } + + if (val && rand()%100 < rate) { + diff += val; + } + return diff; +} + +/*========================================== * C—ûƒ_ƒ[ƒW *------------------------------------------ */ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type) { int damage,skill; - int race=battle_get_race(target); + int race=status_get_race(target); int weapon; damage = 0; nullpo_retr(0, sd); // ƒf[ƒ‚ƒ“ƒxƒCƒ“(+3 ` +30) vs •sŽ€ or ˆ«–‚ (Ž€l‚͊܂߂Ȃ¢H) - if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 && (battle_check_undead(race,battle_get_elem_type(target)) || race==6) ) + if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 && (battle_check_undead(race,status_get_elem_type(target)) || race==6) ) damage += (skill*(int)(3+(sd->status.base_level+1)*0.05)); // submitted by orn //damage += (skill * 3); @@ -1698,7 +519,7 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int weapon = sd->weapontype2; switch(weapon) { - case 0x01: // ’ZŒ• (Updated By AppleGirl) + case 0x01: // ’ZŒ• Knife case 0x02: // 1HS { // Œ•C—û(+4 ` +40) •Ў茕 ’ZŒ•ŠÜ‚Þ @@ -1716,16 +537,6 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int break; } case 0x04: // 1HL - { - // ‘„C—û(+4 ` +40,+5 ` +50) ‘„ - if((skill = pc_checkskill(sd,KN_SPEARMASTERY)) > 0) { - if(!pc_isriding(sd)) - damage += (skill * 4); // ƒyƒR‚Éæ‚Á‚ĂȂ¢ - else - damage += (skill * 5); // ƒyƒR‚Éæ‚Á‚Ä‚é - } - break; - } case 0x05: // 2HL { // ‘„C—û(+4 ` +40,+5 ` +50) ‘„ @@ -1737,13 +548,7 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int } break; } - case 0x06: // •ÐŽè•€ - { - if((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0) { - damage += (skill * 3); - } - break; - } + case 0x06: // •ÐŽè•€ case 0x07: // Axe by Tato { if((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0) { @@ -1765,7 +570,7 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int break; case 0x0b: // ‹| break; - case 0x00: // ‘fŽè + case 0x00: // ‘fŽè Bare Hands case 0x0c: // Knuckles { // “SŒ(+3 ` +30) ‘fŽè,ƒiƒbƒNƒ‹ @@ -1819,14 +624,16 @@ static struct Damage battle_calc_pet_weapon_attack( struct mob_data *tmd=NULL; int hitrate,flee,cri = 0,atkmin,atkmax; int luk,target_count = 1; - int def1 = battle_get_def(target); - int def2 = battle_get_def2(target); - int t_vit = battle_get_vit(target); + int def1 = status_get_def(target); + int def2 = status_get_def2(target); + int t_vit = status_get_vit(target); struct Damage wd; int damage,damage2=0,type,div_,blewcount=skill_get_blewcount(skill_num,skill_lv); int flag,dmg_lv=0; int t_mode=0,t_race=0,t_size=1,s_race=0,s_ele=0; struct status_change *t_sc_data; + int div_flag=0; // 0: total damage is to be divided by div_ + // 1: damage is distributed,and has to be multiplied by div_ [celest] //return‘O‚̈—‚ª‚ ‚é‚Ì‚Åî•ño—Í•”‚̂ݕÏX if( target == NULL || pd == NULL ){ //src‚Í“à—e‚É’¼ÚG‚ê‚Ä‚¢‚È‚¢‚̂ŃXƒ‹[‚µ‚Ă݂é @@ -1835,8 +642,8 @@ static struct Damage battle_calc_pet_weapon_attack( return wd; } - s_race=battle_get_race(src); - s_ele=battle_get_attack_element(src); + s_race=status_get_race(src); + s_ele=status_get_attack_element(src); // ƒ^[ƒQƒbƒg if(target->type == BL_MOB) @@ -1845,61 +652,70 @@ static struct Damage battle_calc_pet_weapon_attack( memset(&wd,0,sizeof(wd)); return wd; } - t_race=battle_get_race( target ); - t_size=battle_get_size( target ); - t_mode=battle_get_mode( target ); - t_sc_data=battle_get_sc_data( target ); + t_race=status_get_race( target ); + t_size=status_get_size( target ); + t_mode=status_get_mode( target ); + t_sc_data=status_get_sc_data( target ); flag=BF_SHORT|BF_WEAPON|BF_NORMAL; // UŒ‚‚ÌŽí—Þ‚ÌÝ’è // ‰ñ”𗦌vŽZA‰ñ”ð”»’è‚ÍŒã‚Å - flee = battle_get_flee(target); - if(battle_config.agi_penaly_type > 0 || battle_config.vit_penaly_type > 0) - target_count += battle_counttargeted(target,src,battle_config.agi_penaly_count_lv); - if(battle_config.agi_penaly_type > 0) { - if(target_count >= battle_config.agi_penaly_count) { - if(battle_config.agi_penaly_type == 1) - flee = (flee * (100 - (target_count - (battle_config.agi_penaly_count - 1))*battle_config.agi_penaly_num))/100; - else if(battle_config.agi_penaly_type == 2) - flee -= (target_count - (battle_config.agi_penaly_count - 1))*battle_config.agi_penaly_num; + flee = status_get_flee(target); + if(battle_config.agi_penalty_type > 0 || battle_config.vit_penalty_type > 0) + target_count += battle_counttargeted(target,src,battle_config.agi_penalty_count_lv); + if(battle_config.agi_penalty_type > 0) { + if(target_count >= battle_config.agi_penalty_count) { + if(battle_config.agi_penalty_type == 1) + flee = (flee * (100 - (target_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; + else if(battle_config.agi_penalty_type == 2) + flee -= (target_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; if(flee < 1) flee = 1; } } - hitrate=battle_get_hit(src) - flee + 80; + hitrate=status_get_hit(src) - flee + 80; type=0; // normal - div_ = 1; // single attack + if (skill_num > 0) { + div_ = skill_get_num(skill_num,skill_lv); + if (div_ < 1) div_ = 1; //Avoid the rare case where the db says div_ is 0 and below + } + else div_ = 1; // single attack - luk=battle_get_luk(src); + luk=status_get_luk(src); if(battle_config.pet_str) - damage = battle_get_baseatk(src); + damage = status_get_baseatk(src); else damage = 0; if(skill_num==HW_MAGICCRASHER){ /* ƒ}ƒWƒbƒNƒNƒ‰ƒbƒVƒƒ[‚ÍMATK‚ʼn£‚é */ - atkmin = battle_get_matk1(src); - atkmax = battle_get_matk2(src); + atkmin = status_get_matk1(src); + atkmax = status_get_matk2(src); }else{ - atkmin = battle_get_atk(src); - atkmax = battle_get_atk2(src); + atkmin = status_get_atk(src); + atkmax = status_get_atk2(src); } - if(mob_db[pd->class].range>3 ) + if(mob_db[pd->class_].range>3 ) flag=(flag&~BF_RANGEMASK)|BF_LONG; if(atkmin > atkmax) atkmin = atkmax; - cri = battle_get_critical(src); - cri -= battle_get_luk(target) * 2; // luk/5*10 => target_luk*2 not target_luk*3 + cri = status_get_critical(src); + cri -= status_get_luk(target) * 2; // luk/5*10 => target_luk*2 not target_luk*3 if(battle_config.enemy_critical_rate != 100) { cri = cri*battle_config.enemy_critical_rate/100; if(cri < 1) cri = 1; } - if(t_sc_data != NULL && t_sc_data[SC_SLEEP].timer!=-1 ) - cri <<=1; + if(t_sc_data) { + if (t_sc_data[SC_SLEEP].timer!=-1) + cri <<=1; + if(t_sc_data[SC_JOINTBEAT].timer != -1 && + t_sc_data[SC_JOINTBEAT].val2 == 6) // Always take crits with Neck broken by Joint Beat [DracoRPG] + cri = 1000; + } - if(skill_num == 0 && skill_lv >= 0 && battle_config.enemy_critical && (rand() % 1000) < cri) + if(skill_num == 0 && battle_config.enemy_critical && (rand() % 1000) < cri) { damage += atkmax; type = 0x0a; @@ -1930,14 +746,14 @@ static struct Damage battle_calc_pet_weapon_attack( hitrate = (hitrate*(100+5*skill_lv))/100; break; case SM_MAGNUM: // ƒ}ƒOƒiƒ€ƒuƒŒƒCƒN - damage = damage*(5*skill_lv +(wflag)?65:115 )/100; + damage = damage*(wflag > 1 ? 5*skill_lv+115 : 30*skill_lv+100)/100; + hitrate = (hitrate*(100+10*skill_lv))/100; break; case MC_MAMMONITE: // ƒƒ}[ƒiƒCƒg damage = damage*(100+ 50*skill_lv)/100; break; case AC_DOUBLE: // ƒ_ƒuƒ‹ƒXƒgƒŒƒCƒtƒBƒ“ƒO damage = damage*(180+ 20*skill_lv)/100; - div_=2; flag=(flag&~BF_RANGEMASK)|BF_LONG; break; case AC_SHOWER: // ƒAƒ[ƒVƒƒƒ[ @@ -1952,7 +768,7 @@ static struct Damage battle_calc_pet_weapon_attack( damage = damage*(100+ 10*skill_lv)/100; hitrate = hitrate*(100+5*skill_lv)/100; div_=t_size+1; - damage*=div_; + div_flag = 1; break; case KN_SPEARSTAB: // ƒXƒsƒAƒXƒ^ƒu damage = damage*(100+ 15*skill_lv)/100; @@ -1970,14 +786,13 @@ static struct Damage battle_calc_pet_weapon_attack( if(skill_lv>9 && wflag==2) damage2+=damage/4; if(skill_lv>9 && wflag==3) damage2+=damage/2; damage +=damage2; - blewcount=0; break; case KN_BOWLINGBASH: // ƒ{ƒEƒŠƒ“ƒOƒoƒbƒVƒ… damage = damage*(100+ 50*skill_lv)/100; blewcount=0; break; case AS_GRIMTOOTH: - damage = damage*(100+ 20*skill_lv)/100; + damage = damage*(100+ 20*skill_lv)/100; break; case AS_POISONREACT: // celest s_ele = 0; @@ -1985,7 +800,6 @@ static struct Damage battle_calc_pet_weapon_attack( break; case AS_SONICBLOW: // ƒ\ƒjƒbƒNƒuƒƒE damage = damage*(300+ 50*skill_lv)/100; - div_=8; break; case TF_SPRINKLESAND: // »‚Ü‚« damage = damage*125/100; @@ -1995,8 +809,7 @@ static struct Damage battle_calc_pet_weapon_attack( break; // ˆÈ‰ºMOB case NPC_COMBOATTACK: // ‘½’iUŒ‚ - div_=skill_get_num(skill_num,skill_lv); - damage *= div_; + div_flag = 1; break; case NPC_RANDOMATTACK: // ƒ‰ƒ“ƒ_ƒ€ATKUŒ‚ damage = damage*(50+rand()%150)/100; @@ -2009,6 +822,7 @@ static struct Damage battle_calc_pet_weapon_attack( case NPC_POISONATTACK: case NPC_HOLYATTACK: case NPC_DARKNESSATTACK: + case NPC_UNDEADATTACK: case NPC_TELEKINESISATTACK: div_= pd->skillduration; // [Valaris] break; @@ -2043,27 +857,27 @@ static struct Damage battle_calc_pet_weapon_attack( break; case CR_HOLYCROSS: // ƒz[ƒŠ[ƒNƒƒX damage = damage*(100+ 35*skill_lv)/100; - div_=2; break; case CR_GRANDCROSS: hitrate= 1000000; break; case AM_DEMONSTRATION: // ƒfƒ‚ƒ“ƒXƒgƒŒ[ƒVƒ‡ƒ“ + hitrate= 1000000; damage = damage*(100+ 20*skill_lv)/100; damage2 = damage2*(100+ 20*skill_lv)/100; break; case AM_ACIDTERROR: // ƒAƒVƒbƒhƒeƒ‰[ + hitrate = 1000000; damage = damage*(100+ 40*skill_lv)/100; damage2 = damage2*(100+ 40*skill_lv)/100; break; case MO_FINGEROFFENSIVE: //Žw’e damage = damage * (125 + 25 * skill_lv) / 100; - div_ = 1; flag=(flag&~BF_RANGEMASK)|BF_LONG; //orn break; case MO_INVESTIGATE: // ” ™¤ if(def1 < 1000000) - damage = damage*(100+ 75*skill_lv)/100 * (def1 + def2)/100; + damage = damage*(100+ 75*skill_lv)/100 * (def1 + def2)/50; hitrate = 1000000; s_ele = 0; break; @@ -2074,32 +888,30 @@ static struct Damage battle_calc_pet_weapon_attack( break; case MO_CHAINCOMBO: // ˜A‘Ŷ damage = damage*(150+ 50*skill_lv)/100; - div_=4; break; case MO_COMBOFINISH: // –Ò—´Œ damage = damage*(240+ 60*skill_lv)/100; break; case DC_THROWARROW: // –‚¿ - damage = damage*(100+ 50 * skill_lv)/100; + damage = damage*(60+ 40 * skill_lv)/100; flag=(flag&~BF_RANGEMASK)|BF_LONG; break; case BA_MUSICALSTRIKE: // ƒ~ƒ…[ƒWƒJƒ‹ƒXƒgƒ‰ƒCƒN - damage = damage*(100+ 50 * skill_lv)/100; + damage = damage*(60+ 40 * skill_lv)/100; flag=(flag&~BF_RANGEMASK)|BF_LONG; break; case CH_TIGERFIST: // •šŒÕŒ - damage = damage*(100+ 60*skill_lv)/100; + damage = damage*(40+ 100*skill_lv)/100; break; case CH_CHAINCRUSH: // ˜A’Œ•öŒ‚ - damage = damage*(100+ 60*skill_lv)/100; - div_=skill_get_num(skill_num,skill_lv); + damage = damage*(400+ 100*skill_lv)/100; break; case CH_PALMSTRIKE: // –ÒŒÕd”hŽR - damage = damage*(50+ 100*skill_lv)/100; + damage = damage*(200+ 100*skill_lv)/100; break; case LK_SPIRALPIERCE: /* ƒXƒpƒCƒ‰ƒ‹ƒsƒA[ƒX */ damage = damage*(100+ 50*skill_lv)/100; //‘‰Á—Ê‚ª•ª‚©‚ç‚È‚¢‚̂œK“–‚É - div_=5; + flag=(flag&~BF_RANGEMASK)|BF_LONG; if(target->type == BL_PC) ((struct map_session_data *)target)->canmove_tick = gettick() + 1000; else if(target->type == BL_MOB) @@ -2119,31 +931,35 @@ static struct Damage battle_calc_pet_weapon_attack( break; case CG_ARROWVULCAN: /* ƒAƒ[ƒoƒ‹ƒJƒ“ */ damage = damage*(200+100*skill_lv)/100; - div_=9; break; case AS_SPLASHER: /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ[ */ damage = damage*(200+20*skill_lv)/100; + hitrate = 1000000; break; } + if (div_flag && div_ > 1) { // [Skotlex] + damage *= div_; + damage2 *= div_; + } } if( skill_num!=NPC_CRITICALSLASH ){ // ‘Î Û‚Ì–hŒä—͂ɂæ‚éƒ_ƒ[ƒW‚ÌŒ¸ // ƒfƒBƒoƒCƒ“ƒvƒƒeƒNƒVƒ‡ƒ“i‚±‚±‚Å‚¢‚¢‚Ì‚©‚ÈHj - if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && def1 < 1000000 ) { //DEF, VIT–³Ž‹ + if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && skill_num != AM_ACIDTERROR && def1 < 1000000 ) { //DEF, VIT–³Ž‹ int t_def; - target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penaly_count_lv); - if(battle_config.vit_penaly_type > 0) { - if(target_count >= battle_config.vit_penaly_count) { - if(battle_config.vit_penaly_type == 1) { - def1 = (def1 * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100; - def2 = (def2 * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100; - t_vit = (t_vit * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100; + target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penalty_count_lv); + if(battle_config.vit_penalty_type > 0) { + if(target_count >= battle_config.vit_penalty_count) { + if(battle_config.vit_penalty_type == 1) { + def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; + def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; + t_vit = (t_vit * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; } - else if(battle_config.vit_penaly_type == 2) { - def1 -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num; - def2 -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num; - t_vit -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num; + else if(battle_config.vit_penalty_type == 2) { + def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; + def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; + t_vit -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; } if(def1 < 0) def1 = 0; if(def2 < 1) def2 = 1; @@ -2168,10 +984,10 @@ static struct Damage battle_calc_pet_weapon_attack( // ‰ñ”ðC³ if( hitrate < 1000000 && t_sc_data ) { // •K’†UŒ‚ if(t_sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG) - hitrate -= 50; + hitrate -= 75; if (t_sc_data[SC_SLEEP].timer!=-1 || // ‡–°‚Í•K’† t_sc_data[SC_STAN].timer!=-1 || // ƒXƒ^ƒ“‚Í•K’† - t_sc_data[SC_FREEZE].timer!=-1 || + t_sc_data[SC_FREEZE].timer!=-1 || (t_sc_data[SC_STONE].timer!=-1 && t_sc_data[SC_STONE].val2==0)) // “€Œ‹‚Í•K’† hitrate = 1000000; } @@ -2184,13 +1000,13 @@ static struct Damage battle_calc_pet_weapon_attack( dmg_lv = ATK_DEF; } - + if(t_sc_data) { int cardfix=100; if(t_sc_data[SC_DEFENDER].timer != -1 && flag&BF_LONG) cardfix=cardfix*(100-t_sc_data[SC_DEFENDER].val2)/100; if(t_sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG) - cardfix=cardfix*(100-t_sc_data[SC_FOGWALL].val2)/100; + cardfix=cardfix*50/100; if(cardfix != 100) damage=damage*cardfix/100; } @@ -2198,22 +1014,22 @@ static struct Damage battle_calc_pet_weapon_attack( // ‘® «‚Ì“K—p if(skill_num != 0 || s_ele != 0 || !battle_config.pet_attack_attr_none) - damage=battle_attr_fix(damage, s_ele, battle_get_element(target) ); + damage=battle_attr_fix(damage, s_ele, status_get_element(target) ); if(skill_num==PA_PRESSURE) /* ƒvƒŒƒbƒVƒƒ[ •K’†? */ damage = 500+300*skill_lv; // ƒCƒ“ƒxƒiƒ€C³ if(skill_num==TF_POISON){ - damage = battle_attr_fix(damage + 15*skill_lv, s_ele, battle_get_element(target) ); + damage = battle_attr_fix(damage + 15*skill_lv, s_ele, status_get_element(target) ); } if(skill_num==MC_CARTREVOLUTION){ - damage = battle_attr_fix(damage, 0, battle_get_element(target) ); + damage = battle_attr_fix(damage, 0, status_get_element(target) ); } // Š®‘S‰ñ”ð‚Ì”»’è if(battle_config.enemy_perfect_flee) { - if(skill_num == 0 && skill_lv >= 0 && tmd!=NULL && rand()%1000 < battle_get_flee2(target) ){ + if(skill_num == 0 && tmd!=NULL && rand()%1000 < status_get_flee2(target) ){ damage=0; type=0x0b; dmg_lv = ATK_LUCKY; @@ -2231,10 +1047,10 @@ static struct Damage battle_calc_pet_weapon_attack( wd.damage2=0; wd.type=type; wd.div_=div_; - wd.amotion=battle_get_amotion(src); + wd.amotion=status_get_amotion(src); if(skill_num == KN_AUTOCOUNTER) wd.amotion >>= 1; - wd.dmotion=battle_get_dmotion(target); + wd.dmotion=status_get_dmotion(target); wd.blewcount=blewcount; wd.flag=flag; wd.dmg_lv=dmg_lv; @@ -2249,16 +1065,18 @@ static struct Damage battle_calc_mob_weapon_attack( struct mob_data* md=(struct mob_data *)src,*tmd=NULL; int hitrate,flee,cri = 0,atkmin,atkmax; int luk,target_count = 1; - int def1 = battle_get_def(target); - int def2 = battle_get_def2(target); - int t_vit = battle_get_vit(target); + int def1 = status_get_def(target); + int def2 = status_get_def2(target); + int t_vit = status_get_vit(target); struct Damage wd; int damage,damage2=0,type,div_,blewcount=skill_get_blewcount(skill_num,skill_lv); int flag,skill,ac_flag = 0,dmg_lv = 0; - int t_mode=0,t_race=0,t_size=1,s_race=0,s_ele=0; + int t_mode=0,t_race=0,t_size=1,s_race=0,s_ele=0,s_size=0,s_race2=0; struct status_change *sc_data,*t_sc_data; short *sc_count; short *option, *opt1, *opt2; + int div_flag=0; // 0: total damage is to be divided by div_ + // 1: damage is distributed,and has to be multiplied by div_ [celest] //return‘O‚̈—‚ª‚ ‚é‚Ì‚Åî•ño—Í•”‚̂ݕÏX if( src == NULL || target == NULL || md == NULL ){ @@ -2267,35 +1085,37 @@ static struct Damage battle_calc_mob_weapon_attack( return wd; } - s_race=battle_get_race(src); - s_ele=battle_get_attack_element(src); - sc_data=battle_get_sc_data(src); - sc_count=battle_get_sc_count(src); - option=battle_get_option(src); - opt1=battle_get_opt1(src); - opt2=battle_get_opt2(src); + s_race = status_get_race(src); + s_ele = status_get_attack_element(src); + s_size = status_get_size(src); + sc_data = status_get_sc_data(src); + sc_count = status_get_sc_count(src); + option = status_get_option(src); + opt1 = status_get_opt1(src); + opt2 = status_get_opt2(src); + s_race2 = status_get_race2(src); // ƒ^[ƒQƒbƒg - if(target->type==BL_PC) - tsd=(struct map_session_data *)target; - else if(target->type==BL_MOB) - tmd=(struct mob_data *)target; - t_race=battle_get_race( target ); - t_size=battle_get_size( target ); - t_mode=battle_get_mode( target ); - t_sc_data=battle_get_sc_data( target ); - - if((skill_num == 0 || (target->type == BL_PC && battle_config.pc_auto_counter_type&2) || - (target->type == BL_MOB && battle_config.monster_auto_counter_type&2)) && skill_lv >= 0) { + if(target->type == BL_PC) + tsd = (struct map_session_data *)target; + else if(target->type == BL_MOB) + tmd = (struct mob_data *)target; + t_race = status_get_race( target ); + t_size = status_get_size( target ); + t_mode = status_get_mode( target ); + t_sc_data = status_get_sc_data( target ); + + if(skill_num == 0 || (target->type == BL_PC && battle_config.pc_auto_counter_type&2) || + (target->type == BL_MOB && battle_config.monster_auto_counter_type&2)) { if(skill_num != CR_GRANDCROSS && t_sc_data && t_sc_data[SC_AUTOCOUNTER].timer != -1) { - int dir = map_calc_dir(src,target->x,target->y),t_dir = battle_get_dir(target); + int dir = map_calc_dir(src,target->x,target->y),t_dir = status_get_dir(target); int dist = distance(src->x,src->y,target->x,target->y); if(dist <= 0 || map_check_dir(dir,t_dir) ) { memset(&wd,0,sizeof(wd)); t_sc_data[SC_AUTOCOUNTER].val3 = 0; t_sc_data[SC_AUTOCOUNTER].val4 = 1; if(sc_data && sc_data[SC_AUTOCOUNTER].timer == -1) { - int range = battle_get_range(target); + int range = status_get_range(target); if((target->type == BL_PC && ((struct map_session_data *)target)->status.weapon != 11 && dist <= range+1) || (target->type == BL_MOB && range <= 3 && dist <= range+1) ) t_sc_data[SC_AUTOCOUNTER].val3 = src->id; @@ -2312,37 +1132,40 @@ static struct Damage battle_calc_mob_weapon_attack( flag=BF_SHORT|BF_WEAPON|BF_NORMAL; // UŒ‚‚ÌŽí—Þ‚ÌÝ’è // ‰ñ”𗦌vŽZA‰ñ”ð”»’è‚ÍŒã‚Å - flee = battle_get_flee(target); - if(battle_config.agi_penaly_type > 0 || battle_config.vit_penaly_type > 0) - target_count += battle_counttargeted(target,src,battle_config.agi_penaly_count_lv); - if(battle_config.agi_penaly_type > 0) { - if(target_count >= battle_config.agi_penaly_count) { - if(battle_config.agi_penaly_type == 1) - flee = (flee * (100 - (target_count - (battle_config.agi_penaly_count - 1))*battle_config.agi_penaly_num))/100; - else if(battle_config.agi_penaly_type == 2) - flee -= (target_count - (battle_config.agi_penaly_count - 1))*battle_config.agi_penaly_num; + flee = status_get_flee(target); + if(battle_config.agi_penalty_type > 0 || battle_config.vit_penalty_type > 0) + target_count += battle_counttargeted(target,src,battle_config.agi_penalty_count_lv); + if(battle_config.agi_penalty_type > 0) { + if(target_count >= battle_config.agi_penalty_count) { + if(battle_config.agi_penalty_type == 1) + flee = (flee * (100 - (target_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; + else if(battle_config.agi_penalty_type == 2) + flee -= (target_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; if(flee < 1) flee = 1; } } - hitrate=battle_get_hit(src) - flee + 80; + hitrate=status_get_hit(src) - flee + 80; type=0; // normal - div_ = 1; // single attack + if (skill_num > 0) { + div_ = skill_get_num(skill_num,skill_lv); + if (div_ < 1) div_ = 1; //Avoid the rare case where the db says div_ is 0 and below + } else div_ = 1; // single attack - luk=battle_get_luk(src); + luk=status_get_luk(src); if(battle_config.enemy_str) - damage = battle_get_baseatk(src); + damage = status_get_baseatk(src); else damage = 0; if(skill_num==HW_MAGICCRASHER){ /* ƒ}ƒWƒbƒNƒNƒ‰ƒbƒVƒƒ[‚ÍMATK‚ʼn£‚é */ - atkmin = battle_get_matk1(src); - atkmax = battle_get_matk2(src); + atkmin = status_get_matk1(src); + atkmax = status_get_matk2(src); }else{ - atkmin = battle_get_atk(src); - atkmax = battle_get_atk2(src); + atkmin = status_get_atk(src); + atkmax = status_get_atk2(src); } - if(mob_db[md->class].range>3 ) + if(mob_db[md->class_].range>3 ) flag=(flag&~BF_RANGEMASK)|BF_LONG; if(atkmin > atkmax) atkmin = atkmax; @@ -2351,15 +1174,20 @@ static struct Damage battle_calc_mob_weapon_attack( atkmin=atkmax; } - cri = battle_get_critical(src); - cri -= battle_get_luk(target) * 3; + cri = status_get_critical(src); + cri -= status_get_luk(target) * 3; if(battle_config.enemy_critical_rate != 100) { cri = cri*battle_config.enemy_critical_rate/100; if(cri < 1) cri = 1; } - if(t_sc_data != NULL && t_sc_data[SC_SLEEP].timer!=-1 ) // ‡–°’†‚̓NƒŠƒeƒBƒJƒ‹‚ª”{‚É - cri <<=1; + if(t_sc_data) { + if (t_sc_data[SC_SLEEP].timer!=-1 ) // ‡–°’†‚̓NƒŠƒeƒBƒJƒ‹‚ª”{‚É + cri <<=1; + if(t_sc_data[SC_JOINTBEAT].timer != -1 && + t_sc_data[SC_JOINTBEAT].val2 == 6) // Always take crits with Neck broken by Joint Beat [DracoRPG] + cri = 1000; + } if(ac_flag) cri = 1000; @@ -2395,9 +1223,9 @@ static struct Damage battle_calc_mob_weapon_attack( // ƒ\ƒjƒbƒNƒuƒ[ if(sc_data){ //ó‘ÔˆÙí’†‚̃_ƒ[ƒW’ljÁ if(sc_data[SC_OVERTHRUST].timer!=-1) // ƒI[ƒo[ƒgƒ‰ƒXƒg - damage += damage*(5*sc_data[SC_OVERTHRUST].val1)/100; + damage += damage*(5*sc_data[SC_OVERTHRUST].val1)/100; if(sc_data[SC_TRUESIGHT].timer!=-1) // ƒgƒDƒ‹[ƒTƒCƒg - damage += damage*(2*sc_data[SC_TRUESIGHT].val1)/100; + damage += damage*(2*sc_data[SC_TRUESIGHT].val1)/100; if(sc_data[SC_BERSERK].timer!=-1) // ƒo[ƒT[ƒN damage += damage*2; if(sc_data && sc_data[SC_AURABLADE].timer!=-1) //[DracoRPG] @@ -2416,14 +1244,14 @@ static struct Damage battle_calc_mob_weapon_attack( hitrate = (hitrate*(100+5*skill_lv))/100; break; case SM_MAGNUM: // ƒ}ƒOƒiƒ€ƒuƒŒƒCƒN - damage = damage*(5*skill_lv +(wflag)?65:115 )/100; + damage = damage*(wflag > 1 ? 5*skill_lv+115 : 30*skill_lv+100)/100; + hitrate = (hitrate*(100+10*skill_lv))/100; break; case MC_MAMMONITE: // ƒƒ}[ƒiƒCƒg damage = damage*(100+ 50*skill_lv)/100; break; case AC_DOUBLE: // ƒ_ƒuƒ‹ƒXƒgƒŒƒCƒtƒBƒ“ƒO damage = damage*(180+ 20*skill_lv)/100; - div_=2; flag=(flag&~BF_RANGEMASK)|BF_LONG; break; case AC_SHOWER: // ƒAƒ[ƒVƒƒƒ[ @@ -2436,9 +1264,9 @@ static struct Damage battle_calc_mob_weapon_attack( break; case KN_PIERCE: // ƒsƒA[ƒX damage = damage*(100+ 10*skill_lv)/100; - hitrate=hitrate*(100+5*skill_lv)/100; - div_=t_size+1; - damage*=div_; + hitrate = hitrate*(100+5*skill_lv)/100; + div_ = t_size+1; + div_flag = 1; break; case KN_SPEARSTAB: // ƒXƒsƒAƒXƒ^ƒu damage = damage*(100+ 15*skill_lv)/100; @@ -2456,7 +1284,6 @@ static struct Damage battle_calc_mob_weapon_attack( if(skill_lv>9 && wflag==2) damage2+=damage/4; if(skill_lv>9 && wflag==3) damage2+=damage/2; damage +=damage2; - blewcount=0; break; case KN_BOWLINGBASH: // ƒ{ƒEƒŠƒ“ƒOƒoƒbƒVƒ… damage = damage*(100+ 50*skill_lv)/100; @@ -2470,7 +1297,7 @@ static struct Damage battle_calc_mob_weapon_attack( flag=(flag&~BF_SKILLMASK)|BF_NORMAL; break; case AS_GRIMTOOTH: - damage = damage*(100+ 20*skill_lv)/100; + damage = damage*(100+ 20*skill_lv)/100; break; case AS_POISONREACT: // celest s_ele = 0; @@ -2478,7 +1305,6 @@ static struct Damage battle_calc_mob_weapon_attack( break; case AS_SONICBLOW: // ƒ\ƒjƒbƒNƒuƒƒE damage = damage*(300+ 50*skill_lv)/100; - div_=8; break; case TF_SPRINKLESAND: // »‚Ü‚« damage = damage*125/100; @@ -2488,8 +1314,7 @@ static struct Damage battle_calc_mob_weapon_attack( break; // ˆÈ‰ºMOB case NPC_COMBOATTACK: // ‘½’iUŒ‚ - div_=skill_get_num(skill_num,skill_lv); - damage *= div_; + div_flag = 1; break; case NPC_RANDOMATTACK: // ƒ‰ƒ“ƒ_ƒ€ATKUŒ‚ damage = damage*(50+rand()%150)/100; @@ -2502,6 +1327,7 @@ static struct Damage battle_calc_mob_weapon_attack( case NPC_POISONATTACK: case NPC_HOLYATTACK: case NPC_DARKNESSATTACK: + case NPC_UNDEADATTACK: case NPC_TELEKINESISATTACK: damage = damage*(100+25*(skill_lv-1))/100; break; @@ -2536,27 +1362,27 @@ static struct Damage battle_calc_mob_weapon_attack( break; case CR_HOLYCROSS: // ƒz[ƒŠ[ƒNƒƒX damage = damage*(100+ 35*skill_lv)/100; - div_=2; break; case CR_GRANDCROSS: hitrate= 1000000; break; case AM_DEMONSTRATION: // ƒfƒ‚ƒ“ƒXƒgƒŒ[ƒVƒ‡ƒ“ + hitrate = 1000000; damage = damage*(100+ 20*skill_lv)/100; damage2 = damage2*(100+ 20*skill_lv)/100; break; case AM_ACIDTERROR: // ƒAƒVƒbƒhƒeƒ‰[ + hitrate = 1000000; damage = damage*(100+ 40*skill_lv)/100; damage2 = damage2*(100+ 40*skill_lv)/100; break; case MO_FINGEROFFENSIVE: //Žw’e damage = damage * (125 + 25 * skill_lv) / 100; - div_ = 1; flag=(flag&~BF_RANGEMASK)|BF_LONG; //orn break; case MO_INVESTIGATE: // ” ™¤ if(def1 < 1000000) - damage = damage*(100+ 75*skill_lv)/100 * (def1 + def2)/100; + damage = damage*(100+ 75*skill_lv)/100 * (def1 + def2)/50; hitrate = 1000000; s_ele = 0; break; @@ -2567,32 +1393,30 @@ static struct Damage battle_calc_mob_weapon_attack( break; case MO_CHAINCOMBO: // ˜A‘Ŷ damage = damage*(150+ 50*skill_lv)/100; - div_=4; break; case BA_MUSICALSTRIKE: // ƒ~ƒ…[ƒWƒJƒ‹ƒXƒgƒ‰ƒCƒN - damage = damage*(100+ 50 * skill_lv)/100; + damage = damage*(60+ 40 * skill_lv)/100; flag=(flag&~BF_RANGEMASK)|BF_LONG; break; case DC_THROWARROW: // –‚¿ - damage = damage*(100+ 50 * skill_lv)/100; + damage = damage*(60+ 40 * skill_lv)/100; flag=(flag&~BF_RANGEMASK)|BF_LONG; break; case MO_COMBOFINISH: // –Ò—´Œ damage = damage*(240+ 60*skill_lv)/100; break; case CH_TIGERFIST: // •šŒÕŒ - damage = damage*(100+ 20*skill_lv)/100; + damage = damage*(40+ 100*skill_lv)/100; break; case CH_CHAINCRUSH: // ˜A’Œ•öŒ‚ - damage = damage*(100+ 60*skill_lv)/100; - div_=skill_get_num(skill_num,skill_lv); + damage = damage*(400+ 100*skill_lv)/100; break; case CH_PALMSTRIKE: // –ÒŒÕd”hŽR - damage = damage*(50+ 100*skill_lv)/100; + damage = damage*(200+ 100*skill_lv)/100; break; case LK_SPIRALPIERCE: /* ƒXƒpƒCƒ‰ƒ‹ƒsƒA[ƒX */ damage = damage*(100+ 50*skill_lv)/100; //‘‰Á—Ê‚ª•ª‚©‚ç‚È‚¢‚̂œK“–‚É - div_=5; + flag=(flag&~BF_RANGEMASK)|BF_LONG; if(tsd) tsd->canmove_tick = gettick() + 1000; else if(tmd) @@ -2612,31 +1436,35 @@ static struct Damage battle_calc_mob_weapon_attack( break; case CG_ARROWVULCAN: /* ƒAƒ[ƒoƒ‹ƒJƒ“ */ damage = damage*(200+100*skill_lv)/100; - div_=9; break; case AS_SPLASHER: /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ[ */ damage = damage*(200+20*skill_lv)/100; + hitrate = 1000000; break; } + if (div_flag && div_ > 1) { // [Skotlex] + damage *= div_; + damage2 *= div_; + } } if( skill_num!=NPC_CRITICALSLASH ){ // ‘Î Û‚Ì–hŒä—͂ɂæ‚éƒ_ƒ[ƒW‚ÌŒ¸ // ƒfƒBƒoƒCƒ“ƒvƒƒeƒNƒVƒ‡ƒ“i‚±‚±‚Å‚¢‚¢‚Ì‚©‚ÈHj - if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && def1 < 1000000) { //DEF, VIT–³Ž‹ + if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && skill_num != AM_ACIDTERROR && def1 < 1000000) { //DEF, VIT–³Ž‹ int t_def; - target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penaly_count_lv); - if(battle_config.vit_penaly_type > 0) { - if(target_count >= battle_config.vit_penaly_count) { - if(battle_config.vit_penaly_type == 1) { - def1 = (def1 * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100; - def2 = (def2 * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100; - t_vit = (t_vit * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100; + target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penalty_count_lv); + if(battle_config.vit_penalty_type > 0) { + if(target_count >= battle_config.vit_penalty_count) { + if(battle_config.vit_penalty_type == 1) { + def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; + def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; + t_vit = (t_vit * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; } - else if(battle_config.vit_penaly_type == 2) { - def1 -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num; - def2 -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num; - t_vit -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num; + else if(battle_config.vit_penalty_type == 2) { + def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; + def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; + t_vit -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; } if(def1 < 0) def1 = 0; if(def2 < 1) def2 = 1; @@ -2644,7 +1472,7 @@ static struct Damage battle_calc_mob_weapon_attack( } } t_def = def2*8/10; - if(battle_check_undead(s_race,battle_get_elem_type(src)) || s_race==6) + if(battle_check_undead(s_race,status_get_elem_type(src)) || s_race==6) if(tsd && (skill=pc_checkskill(tsd,AL_DP)) > 0 ) t_def += skill* (int) (3 + (tsd->status.base_level+1)*0.04); // submitted by orn //t_def += skill*3; @@ -2666,10 +1494,10 @@ static struct Damage battle_calc_mob_weapon_attack( // ‰ñ”ðC³ if( hitrate < 1000000 && t_sc_data ) { // •K’†UŒ‚ if(t_sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG) - hitrate -= 50; + hitrate -= 75; if (t_sc_data[SC_SLEEP].timer!=-1 || // ‡–°‚Í•K’† t_sc_data[SC_STAN].timer!=-1 || // ƒXƒ^ƒ“‚Í•K’† - t_sc_data[SC_FREEZE].timer!=-1 || + t_sc_data[SC_FREEZE].timer!=-1 || (t_sc_data[SC_STONE].timer!=-1 && t_sc_data[SC_STONE].val2==0)) // “€Œ‹‚Í•K’† hitrate = 1000000; } @@ -2686,16 +1514,24 @@ static struct Damage battle_calc_mob_weapon_attack( int cardfix=100,i; cardfix=cardfix*(100-tsd->subele[s_ele])/100; // ‘® «‚É‚æ‚éƒ_ƒ[ƒW‘Ï« cardfix=cardfix*(100-tsd->subrace[s_race])/100; // Ží‘°‚É‚æ‚éƒ_ƒ[ƒW‘Ï« - if(mob_db[md->class].mode & 0x20) + cardfix=cardfix*(100-tsd->subsize[s_size])/100; + cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; // Ží‘°‚É‚æ‚éƒ_ƒ[ƒW‘Ï« + if(mob_db[md->class_].mode & 0x20) cardfix=cardfix*(100-tsd->subrace[10])/100; else cardfix=cardfix*(100-tsd->subrace[11])/100; for(i=0;i<tsd->add_def_class_count;i++) { - if(tsd->add_def_classid[i] == md->class) { + if(tsd->add_def_classid[i] == md->class_) { cardfix=cardfix*(100-tsd->add_def_classrate[i])/100; break; } } + for(i=0;i<tsd->add_damage_class_count2;i++) { + if(tsd->add_damage_classid2[i] == md->class_) { + cardfix=cardfix*(100+tsd->add_damage_classrate2[i])/100; + break; + } + } if(flag&BF_LONG) cardfix=cardfix*(100-tsd->long_attack_def_rate)/100; if(flag&BF_SHORT) @@ -2707,7 +1543,7 @@ static struct Damage battle_calc_mob_weapon_attack( if(t_sc_data[SC_DEFENDER].timer != -1 && flag&BF_LONG) cardfix=cardfix*(100-t_sc_data[SC_DEFENDER].val2)/100; if(t_sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG) - cardfix=cardfix*(100-t_sc_data[SC_FOGWALL].val2)/100; + cardfix=cardfix*50/100; if(cardfix != 100) damage=damage*cardfix/100; } @@ -2721,11 +1557,11 @@ static struct Damage battle_calc_mob_weapon_attack( if(damage < 0) damage = 0; // ‘® «‚Ì“K—p - if (!((battle_config.mob_ghostring_fix == 1) && - (battle_get_element(target) == 8) && - (target->type==BL_PC))) // [MouseJstr] - if(skill_num != 0 || s_ele != 0 || !battle_config.mob_attack_attr_none) - damage=battle_attr_fix(damage, s_ele, battle_get_element(target) ); + if (!((battle_config.mob_ghostring_fix == 1) && + (status_get_elem_type(target) == 8) && + (target->type==BL_PC))) // [MouseJstr] + if(skill_num != 0 || s_ele != 0 || !battle_config.mob_attack_attr_none) + damage=battle_attr_fix(damage, s_ele, status_get_element(target) ); //if(sc_data && sc_data[SC_AURABLADE].timer!=-1) /* ƒI[ƒ‰ƒuƒŒ[ƒh •K’† */ // damage += sc_data[SC_AURABLADE].val1 * 10; @@ -2734,21 +1570,21 @@ static struct Damage battle_calc_mob_weapon_attack( // ƒCƒ“ƒxƒiƒ€C³ if(skill_num==TF_POISON){ - damage = battle_attr_fix(damage + 15*skill_lv, s_ele, battle_get_element(target) ); + damage = battle_attr_fix(damage + 15*skill_lv, s_ele, status_get_element(target) ); } if(skill_num==MC_CARTREVOLUTION){ - damage = battle_attr_fix(damage, 0, battle_get_element(target) ); + damage = battle_attr_fix(damage, 0, status_get_element(target) ); } // Š®‘S‰ñ”ð‚Ì”»’è - if(skill_num == 0 && skill_lv >= 0 && tsd!=NULL && rand()%1000 < battle_get_flee2(target) ){ + if(skill_num == 0 && tsd!=NULL && rand()%1000 < status_get_flee2(target) ){ damage=0; type=0x0b; dmg_lv = ATK_LUCKY; } if(battle_config.enemy_perfect_flee) { - if(skill_num == 0 && skill_lv >= 0 && tmd!=NULL && rand()%1000 < battle_get_flee2(target) ){ + if(skill_num == 0 && tmd!=NULL && rand()%1000 < status_get_flee2(target) ){ damage=0; type=0x0b; dmg_lv = ATK_LUCKY; @@ -2769,10 +1605,10 @@ static struct Damage battle_calc_mob_weapon_attack( wd.damage2=0; wd.type=type; wd.div_=div_; - wd.amotion=battle_get_amotion(src); + wd.amotion=status_get_amotion(src); if(skill_num == KN_AUTOCOUNTER) wd.amotion >>= 1; - wd.dmotion=battle_get_dmotion(target); + wd.dmotion=status_get_dmotion(target); wd.blewcount=blewcount; wd.flag=flag; wd.dmg_lv=dmg_lv; @@ -2791,14 +1627,14 @@ static struct Damage battle_calc_pc_weapon_attack( int hitrate,flee,cri = 0,atkmin,atkmax; int dex,luk,target_count = 1; int no_cardfix=0; - int def1 = battle_get_def(target); - int def2 = battle_get_def2(target); -// int mdef1, mdef2; - int t_vit = battle_get_vit(target); + int def1 = status_get_def(target); + int def2 = status_get_def2(target); + int t_vit = status_get_vit(target); struct Damage wd; int damage,damage2,damage3=0,damage4=0,type,div_,blewcount=skill_get_blewcount(skill_num,skill_lv); int flag,skill,dmg_lv = 0; - int t_mode=0,t_race=0,t_size=1,s_race=7,s_ele=0; + int t_mode=0,t_race=0,t_size=1,s_race=7,s_ele=0,s_size=1; + int t_race2=0; struct status_change *sc_data,*t_sc_data; short *sc_count; short *option, *opt1, *opt2; @@ -2806,6 +1642,8 @@ static struct Damage battle_calc_pc_weapon_attack( int watk,watk_,cardfix,t_ele; int da=0,i,t_class,ac_flag = 0; int idef_flag=0,idef_flag_=0; + int div_flag=0; // 0: total damage is to be divided by div_ + // 1: damage is distributed,and has to be multiplied by div_ [celest] //return‘O‚̈—‚ª‚ ‚é‚Ì‚Åî•ño—Í•”‚̂ݕÏX if( src == NULL || target == NULL || sd == NULL ){ @@ -2816,14 +1654,16 @@ static struct Damage battle_calc_pc_weapon_attack( // ƒAƒ^ƒbƒJ[ - s_race=battle_get_race(src); //Ží‘° - s_ele=battle_get_attack_element(src); //‘®« - s_ele_=battle_get_attack_element2(src); //¶Žè‘®« - sc_data=battle_get_sc_data(src); //ƒXƒe[ƒ^ƒXˆÙí - sc_count=battle_get_sc_count(src); //ƒXƒe[ƒ^ƒXˆÙí‚Ì” - option=battle_get_option(src); //‘邯‚©ƒyƒR‚Æ‚©ƒJ[ƒg‚Æ‚© - opt1=battle_get_opt1(src); //Ή»A“€Œ‹AƒXƒ^ƒ“A‡–°AˆÃˆÅ - opt2=battle_get_opt2(src); //“ÅAŽô‚¢A’¾–ÙAˆÃˆÅH + s_race=status_get_race(src); //Ží‘° + s_ele=status_get_attack_element(src); //‘®« + s_ele_=status_get_attack_element2(src); //¶Žè‘®« + s_size=status_get_size(src); + sc_data=status_get_sc_data(src); //ƒXƒe[ƒ^ƒXˆÙí + sc_count=status_get_sc_count(src); //ƒXƒe[ƒ^ƒXˆÙí‚Ì” + option=status_get_option(src); //‘邯‚©ƒyƒR‚Æ‚©ƒJ[ƒg‚Æ‚© + opt1=status_get_opt1(src); //Ή»A“€Œ‹AƒXƒ^ƒ“A‡–°AˆÃˆÅ + opt2=status_get_opt2(src); //“ÅAŽô‚¢A’¾–ÙAˆÃˆÅH + t_race2=status_get_race2(target); if(skill_num != CR_GRANDCROSS) //ƒOƒ‰ƒ“ƒhƒNƒƒX‚łȂ¢‚È‚ç sd->state.attack_type = BF_WEAPON; //UŒ‚ƒ^ƒCƒv‚Í•ŠíUŒ‚ @@ -2833,24 +1673,24 @@ static struct Damage battle_calc_pc_weapon_attack( tsd=(struct map_session_data *)target; //tsd‚É‘ã“ü(tmd‚ÍNULL) else if(target->type==BL_MOB) //‘ÎÛ‚ªMob‚È‚ç tmd=(struct mob_data *)target; //tmd‚É‘ã“ü(tsd‚ÍNULL) - t_race=battle_get_race( target ); //‘ÎÛ‚ÌŽí‘° - t_ele=battle_get_elem_type(target); //‘ÎÛ‚Ì‘®« - t_size=battle_get_size( target ); //‘Îۂ̃TƒCƒY - t_mode=battle_get_mode( target ); //‘ÎÛ‚ÌMode - t_sc_data=battle_get_sc_data( target ); //‘Îۂ̃Xƒe[ƒ^ƒXˆÙí + t_race=status_get_race( target ); //‘ÎÛ‚ÌŽí‘° + t_ele=status_get_elem_type(target); //‘ÎÛ‚Ì‘®« + t_size=status_get_size( target ); //‘Îۂ̃TƒCƒY + t_mode=status_get_mode( target ); //‘ÎÛ‚ÌMode + t_sc_data=status_get_sc_data( target ); //‘Îۂ̃Xƒe[ƒ^ƒXˆÙí //ƒI[ƒgƒJƒEƒ“ƒ^[ˆ—‚±‚±‚©‚ç - if((skill_num == 0 || (target->type == BL_PC && battle_config.pc_auto_counter_type&2) || - (target->type == BL_MOB && battle_config.monster_auto_counter_type&2)) && skill_lv >= 0) { + if(skill_num == 0 || (target->type == BL_PC && battle_config.pc_auto_counter_type&2) || + (target->type == BL_MOB && battle_config.monster_auto_counter_type&2)) { if(skill_num != CR_GRANDCROSS && t_sc_data && t_sc_data[SC_AUTOCOUNTER].timer != -1) { //ƒOƒ‰ƒ“ƒhƒNƒƒX‚łȂA‘ÎÛ‚ªƒI[ƒgƒJƒEƒ“ƒ^[ó‘Ô‚Ìê‡ - int dir = map_calc_dir(src,target->x,target->y),t_dir = battle_get_dir(target); + int dir = map_calc_dir(src,target->x,target->y),t_dir = status_get_dir(target); int dist = distance(src->x,src->y,target->x,target->y); if(dist <= 0 || map_check_dir(dir,t_dir) ) { //‘ÎۂƂ̋——£‚ª0ˆÈ‰ºA‚Ü‚½‚Í‘Îۂ̳–ÊH memset(&wd,0,sizeof(wd)); t_sc_data[SC_AUTOCOUNTER].val3 = 0; t_sc_data[SC_AUTOCOUNTER].val4 = 1; if(sc_data && sc_data[SC_AUTOCOUNTER].timer == -1) { //Ž©•ª‚ªƒI[ƒgƒJƒEƒ“ƒ^[ó‘Ô - int range = battle_get_range(target); + int range = status_get_range(target); if((target->type == BL_PC && ((struct map_session_data *)target)->status.weapon != 11 && dist <= range+1) || //‘ÎÛ‚ªPC‚Å•Ší‚ª‹|–ȂŽË’ö“à (target->type == BL_MOB && range <= 3 && dist <= range+1) ) //‚Ü‚½‚Í‘ÎÛ‚ªMob‚ÅŽË’ö‚ª3ˆÈ‰º‚ÅŽË’ö“à t_sc_data[SC_AUTOCOUNTER].val3 = src->id; @@ -2869,32 +1709,35 @@ static struct Damage battle_calc_pc_weapon_attack( flag=BF_SHORT|BF_WEAPON|BF_NORMAL; // UŒ‚‚ÌŽí—Þ‚ÌÝ’è // ‰ñ”𗦌vŽZA‰ñ”ð”»’è‚ÍŒã‚Å - flee = battle_get_flee(target); - if(battle_config.agi_penaly_type > 0 || battle_config.vit_penaly_type > 0) //AGIAVITƒyƒiƒ‹ƒeƒBݒ肪—LŒø - target_count += battle_counttargeted(target,src,battle_config.agi_penaly_count_lv); //‘ÎÛ‚Ì”‚ðŽZo - if(battle_config.agi_penaly_type > 0) { - if(target_count >= battle_config.agi_penaly_count) { //ƒyƒiƒ‹ƒeƒBÝ’è‚æ‚è‘ÎÛ‚ª‘½‚¢ - if(battle_config.agi_penaly_type == 1) //‰ñ”𗦂ªagi_penaly_num%‚¸‚ÂŒ¸ - flee = (flee * (100 - (target_count - (battle_config.agi_penaly_count - 1))*battle_config.agi_penaly_num))/100; - else if(battle_config.agi_penaly_type == 2) //‰ñ”𗦂ªagi_penaly_num•ªŒ¸ - flee -= (target_count - (battle_config.agi_penaly_count - 1))*battle_config.agi_penaly_num; + flee = status_get_flee(target); + if(battle_config.agi_penalty_type > 0 || battle_config.vit_penalty_type > 0) //AGIAVITƒyƒiƒ‹ƒeƒBݒ肪—LŒø + target_count += battle_counttargeted(target,src,battle_config.agi_penalty_count_lv); //‘ÎÛ‚Ì”‚ðŽZo + if(battle_config.agi_penalty_type > 0) { + if(target_count >= battle_config.agi_penalty_count) { //ƒyƒiƒ‹ƒeƒBÝ’è‚æ‚è‘ÎÛ‚ª‘½‚¢ + if(battle_config.agi_penalty_type == 1) //‰ñ”𗦂ªagi_penalty_num%‚¸‚ÂŒ¸ + flee = (flee * (100 - (target_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; + else if(battle_config.agi_penalty_type == 2) //‰ñ”𗦂ªagi_penalty_num•ªŒ¸ + flee -= (target_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; if(flee < 1) flee = 1; //‰ñ”𗦂ÍÅ’á‚Å‚à1 } } - hitrate=battle_get_hit(src) - flee + 80; //–½’†—¦ŒvŽZ + hitrate=status_get_hit(src) - flee + 80; //–½’†—¦ŒvŽZ type=0; // normal - div_ = 1; // single attack + if (skill_num > 0) { + div_=skill_get_num(skill_num,skill_lv); + if (div_ < 1) div_ = 1; //Avoid the rare case where the db says div_ is 0 and below + } else div_ = 1; // single attack - dex=battle_get_dex(src); //DEX - luk=battle_get_luk(src); //LUK - watk = battle_get_atk(src); //ATK - watk_ = battle_get_atk_(src); //ATK¶Žè + dex=status_get_dex(src); //DEX + luk=status_get_luk(src); //LUK + watk = status_get_atk(src); //ATK + watk_ = status_get_atk_(src); //ATK¶Žè if(skill_num==HW_MAGICCRASHER){ /* ƒ}ƒWƒbƒNƒNƒ‰ƒbƒVƒƒ[‚ÍMATK‚ʼn£‚é */ - damage = damage2 = battle_get_matk1(src); //damega,damega2‰“oêAbase_atk‚̎擾 + damage = damage2 = status_get_matk1(src); //damega,damega2‰“oêAbase_atk‚̎擾 }else{ - damage = damage2 = battle_get_baseatk(&sd->bl); //damega,damega2‰“oêAbase_atk‚̎擾 + damage = damage2 = status_get_baseatk(&sd->bl); //damega,damega2‰“oêAbase_atk‚̎擾 } atkmin = atkmin_ = dex; //Å’áATK‚ÍDEX‚ʼnŠú‰»H sd->state.arrow_atk = 0; //arrow_atk‰Šú‰» @@ -2942,11 +1785,12 @@ static struct Damage battle_calc_pc_weapon_attack( } //ŽO’i¶ - if(skill_num == 0 && skill_lv >= 0 && (skill = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0 && sd->status.weapon <= 16 && !sd->state.arrow_atk) { + //if(skill_num == 0 && skill_lv >= 0 && (skill = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0 && sd->status.weapon <= 16 && !sd->state.arrow_atk) { + if(skill_num == 0 && (skill = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0 && sd->status.weapon <= 16) { // triple blow works with bows ^^ [celest] da = (rand()%100 < (30 - skill)) ? 2:0; } - if(sd->double_rate > 0 && da == 0 && skill_num == 0 && skill_lv >= 0) + if(sd->double_rate > 0 && da == 0 && skill_num == 0) da = (rand()%100 < sd->double_rate) ? 1:0; // ‰ß踘Bƒ{[ƒiƒX @@ -2957,16 +1801,22 @@ static struct Damage battle_calc_pc_weapon_attack( if(da == 0){ //ƒ_ƒuƒ‹ƒAƒ^ƒbƒN‚ª”“®‚µ‚Ä‚¢‚È‚¢ // ƒNƒŠƒeƒBƒJƒ‹ŒvŽZ - cri = battle_get_critical(src); + cri = status_get_critical(src); + cri += sd->critaddrace[t_race]; if(sd->state.arrow_atk) cri += sd->arrow_cri; if(sd->status.weapon == 16) // ƒJƒ^[ƒ‹‚Ìê‡AƒNƒŠƒeƒBƒJƒ‹‚ð”{‚É cri <<=1; - cri -= battle_get_luk(target) * 3; - if(t_sc_data != NULL && t_sc_data[SC_SLEEP].timer!=-1 ) // ‡–°’†‚̓NƒŠƒeƒBƒJƒ‹‚ª”{‚É - cri <<=1; + cri -= status_get_luk(target) * 3; + if(t_sc_data) { + if (t_sc_data[SC_SLEEP].timer!=-1 ) // ‡–°’†‚̓NƒŠƒeƒBƒJƒ‹‚ª”{‚É + cri <<=1; + if(t_sc_data[SC_JOINTBEAT].timer != -1 && + t_sc_data[SC_JOINTBEAT].val2 == 6) // Always take crits with Neck broken by Joint Beat [DracoRPG] + cri = 1000; + } if(ac_flag) cri = 1000; if(skill_num == KN_AUTOCOUNTER) { @@ -2975,25 +1825,29 @@ static struct Damage battle_calc_pc_weapon_attack( else cri <<= 1; } - - if(skill_num == SN_SHARPSHOOTING && rand()%100 < 50) + if(skill_num == SN_SHARPSHOOTING) cri += 200; } if(tsd && tsd->critical_def) cri = cri * (100-tsd->critical_def) / 100; - if(da == 0 && (skill_num==0 || skill_num == KN_AUTOCOUNTER || skill_num == SN_SHARPSHOOTING) && skill_lv >= 0 && //ƒ_ƒuƒ‹ƒAƒ^ƒbƒN‚ª”“®‚µ‚Ä‚¢‚È‚¢ + if(da == 0 && (skill_num==0 || skill_num == KN_AUTOCOUNTER || skill_num == SN_SHARPSHOOTING) && //ƒ_ƒuƒ‹ƒAƒ^ƒbƒN‚ª”“®‚µ‚Ä‚¢‚È‚¢ (rand() % 1000) < cri) // ”»’èiƒXƒLƒ‹‚Ìꇂ͖³Ž‹j { damage += atkmax; damage2 += atkmax_; - if(sd->atk_rate != 100) { - damage = (damage * sd->atk_rate)/100; - damage2 = (damage2 * sd->atk_rate)/100; + if(sd->atk_rate != 100 || sd->weapon_atk_rate != 0) { + if (sd->status.weapon < 16) { + damage = (damage * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100; + damage2 = (damage2 * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100; + } } if(sd->state.arrow_atk) damage += sd->arrow_atk; + + damage += damage * sd->crit_atk_rate / 100; + type = 0x0a; /* if(def1 < 1000000) { @@ -3038,9 +1892,11 @@ static struct Damage battle_calc_pc_weapon_attack( damage2 += atkmin_ + rand() % (atkmax_-atkmin_ + 1); else damage2 += atkmin_ ; - if(sd->atk_rate != 100) { - damage = (damage * sd->atk_rate)/100; - damage2 = (damage2 * sd->atk_rate)/100; + if(sd->atk_rate != 100 || sd->weapon_atk_rate != 0) { + if (sd->status.weapon < 16) { + damage = (damage * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100; + damage2 = (damage2 * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100; + } } if(sd->state.arrow_atk) { @@ -3119,8 +1975,10 @@ static struct Damage battle_calc_pc_weapon_attack( hitrate = (hitrate*(100+5*skill_lv))/100; break; case SM_MAGNUM: // ƒ}ƒOƒiƒ€ƒuƒŒƒCƒN - damage = damage*(5*skill_lv +(wflag)?65:115 )/100; - damage2 = damage2*(5*skill_lv +(wflag)?65:115 )/100; + // 20*skill level+100? i think this will do for now [based on jRO info] + damage = damage*(wflag > 1 ? 5*skill_lv+115 : 30*skill_lv+100)/100; + damage2 = damage2*(wflag > 1 ? 5*skill_lv+115 : 30*skill_lv+100)/100; + hitrate = (hitrate*(100+10*skill_lv))/100; break; case MC_MAMMONITE: // ƒƒ}[ƒiƒCƒg damage = damage*(100+ 50*skill_lv)/100; @@ -3134,7 +1992,6 @@ static struct Damage battle_calc_pc_weapon_attack( } damage = damage*(180+ 20*skill_lv)/100; damage2 = damage2*(180+ 20*skill_lv)/100; - div_=2; if(sd->arrow_ele > 0) { s_ele = sd->arrow_ele; s_ele_ = sd->arrow_ele; @@ -3177,12 +2034,12 @@ static struct Damage battle_calc_pc_weapon_attack( damage2 = damage2*(100+ 10*skill_lv)/100; hitrate=hitrate*(100+5*skill_lv)/100; div_=t_size+1; - damage*=div_; - damage2*=div_; + div_flag=1; break; case KN_SPEARSTAB: // ƒXƒsƒAƒXƒ^ƒu damage = damage*(100+ 15*skill_lv)/100; damage2 = damage2*(100+ 15*skill_lv)/100; + blewcount=0; break; case KN_SPEARBOOMERANG: // ƒXƒsƒAƒu[ƒƒ‰ƒ“ damage = damage*(100+ 50*skill_lv)/100; @@ -3206,7 +2063,6 @@ static struct Damage battle_calc_pc_weapon_attack( if(skill_lv>9 && wflag==2) damage4+=damage2/4; if(skill_lv>9 && wflag==3) damage4+=damage2/2; damage2 +=damage4; - blewcount=0; break; case KN_BOWLINGBASH: // ƒ{ƒEƒŠƒ“ƒOƒoƒbƒVƒ… damage = damage*(100+ 50*skill_lv)/100; @@ -3233,7 +2089,6 @@ static struct Damage battle_calc_pc_weapon_attack( hitrate+=30; // hitrate +30, thanks to midas damage = damage*(300+ 50*skill_lv)/100; damage2 = damage2*(300+ 50*skill_lv)/100; - div_=8; break; case TF_SPRINKLESAND: // »‚Ü‚« damage = damage*125/100; @@ -3241,8 +2096,10 @@ static struct Damage battle_calc_pc_weapon_attack( break; case MC_CARTREVOLUTION: // ƒJ[ƒgƒŒƒ{ƒŠƒ…[ƒVƒ‡ƒ“ if(sd->cart_max_weight > 0 && sd->cart_weight > 0) { - damage = (damage*(150 + pc_checkskill(sd,BS_WEAPONRESEARCH) + (sd->cart_weight*100/sd->cart_max_weight) ) )/100; - damage2 = (damage2*(150 + pc_checkskill(sd,BS_WEAPONRESEARCH) + (sd->cart_weight*100/sd->cart_max_weight) ) )/100; + damage = ( damage*(150 + sd->cart_weight/800) )/100; //fixed CARTREV damage [Lupus] // should be 800, not 80... weight is *10 ^_- [celest] + damage2 = ( damage2*(150 + sd->cart_weight/800) )/100; + //damage = (damage*(150 + pc_checkskill(sd,BS_WEAPONRESEARCH) + (sd->cart_weight*100/sd->cart_max_weight) ) )/100; + //damage2 = (damage2*(150 + pc_checkskill(sd,BS_WEAPONRESEARCH) + (sd->cart_weight*100/sd->cart_max_weight) ) )/100; } else { damage = (damage*150)/100; @@ -3251,9 +2108,7 @@ static struct Damage battle_calc_pc_weapon_attack( break; // ˆÈ‰ºMOB case NPC_COMBOATTACK: // ‘½’iUŒ‚ - div_=skill_get_num(skill_num,skill_lv); - damage *= div_; - damage2 *= div_; + div_flag=1; break; case NPC_RANDOMATTACK: // ƒ‰ƒ“ƒ_ƒ€ATKUŒ‚ damage = damage*(50+rand()%150)/100; @@ -3267,6 +2122,7 @@ static struct Damage battle_calc_pc_weapon_attack( case NPC_POISONATTACK: case NPC_HOLYATTACK: case NPC_DARKNESSATTACK: + case NPC_UNDEADATTACK: case NPC_TELEKINESISATTACK: damage = damage*(100+25*skill_lv)/100; damage2 = damage2*(100+25*skill_lv)/100; @@ -3313,7 +2169,6 @@ static struct Damage battle_calc_pc_weapon_attack( case CR_HOLYCROSS: // ƒz[ƒŠ[ƒNƒƒX damage = damage*(100+ 35*skill_lv)/100; damage2 = damage2*(100+ 35*skill_lv)/100; - div_=2; break; case CR_GRANDCROSS: hitrate= 1000000; @@ -3324,28 +2179,30 @@ static struct Damage battle_calc_pc_weapon_attack( case AM_DEMONSTRATION: // ƒfƒ‚ƒ“ƒXƒgƒŒ[ƒVƒ‡ƒ“ damage = damage*(100+ 20*skill_lv)/100; damage2 = damage2*(100+ 20*skill_lv)/100; + no_cardfix = 1; break; case AM_ACIDTERROR: // ƒAƒVƒbƒhƒeƒ‰[ + hitrate = 1000000; damage = damage*(100+ 40*skill_lv)/100; damage2 = damage2*(100+ 40*skill_lv)/100; + s_ele = 0; + s_ele_ = 0; + no_cardfix = 1; break; case MO_FINGEROFFENSIVE: //Žw’e + damage = damage * (125 + 25 * skill_lv) / 100; + damage2 = damage2 * (125 + 25 * skill_lv) / 100; if(battle_config.finger_offensive_type == 0) { - damage = damage * (125 + 25 * skill_lv) / 100 * sd->spiritball_old; - damage2 = damage2 * (125 + 25 * skill_lv) / 100 * sd->spiritball_old; div_ = sd->spiritball_old; + div_flag = 1; } - else { - damage = damage * (125 + 25 * skill_lv) / 100; - damage2 = damage2 * (125 + 25 * skill_lv) / 100; - div_ = 1; - } + else div_ = 1; flag=(flag&~BF_RANGEMASK)|BF_LONG; //orn break; case MO_INVESTIGATE: // ” ™¤ if(def1 < 1000000) { - damage = damage*(100+ 75*skill_lv)/100 * (def1 + def2)/100; - damage2 = damage2*(100+ 75*skill_lv)/100 * (def1 + def2)/100; + damage = damage*(100+ 75*skill_lv)/100 * (def1 + def2)/50; + damage2 = damage2*(100+ 75*skill_lv)/100 * (def1 + def2)/50; } hitrate = 1000000; s_ele = 0; @@ -3363,26 +2220,19 @@ static struct Damage battle_calc_pc_weapon_attack( case MO_CHAINCOMBO: // ˜A‘Ŷ damage = damage*(150+ 50*skill_lv)/100; damage2 = damage2*(150+ 50*skill_lv)/100; - div_=4; break; case MO_COMBOFINISH: // –Ò—´Œ damage = damage*(240+ 60*skill_lv)/100; damage2 = damage2*(240+ 60*skill_lv)/100; break; case BA_MUSICALSTRIKE: // ƒ~ƒ…[ƒWƒJƒ‹ƒXƒgƒ‰ƒCƒN - if(!sd->state.arrow_atk && sd->arrow_atk > 0) { - int arr = rand()%(sd->arrow_atk+1); - damage += arr; - damage2 += arr; - } - damage = damage*(100+ 50 * skill_lv)/100; - damage2 = damage2*(100+ 50 * skill_lv)/100; + damage = damage*(60+ 40 * skill_lv)/100; + damage2 = damage2*(60+ 40 * skill_lv)/100; if(sd->arrow_ele > 0) { s_ele = sd->arrow_ele; s_ele_ = sd->arrow_ele; } flag=(flag&~BF_RANGEMASK)|BF_LONG; - sd->state.arrow_atk = 1; break; case DC_THROWARROW: // –‚¿ if(!sd->state.arrow_atk && sd->arrow_atk > 0) { @@ -3400,22 +2250,21 @@ static struct Damage battle_calc_pc_weapon_attack( sd->state.arrow_atk = 1; break; case CH_TIGERFIST: // •šŒÕŒ - damage = damage*(100+ 20*skill_lv)/100; - damage2 = damage2*(100+ 20*skill_lv)/100; + damage = damage*(40+ 100*skill_lv)/100; + damage2 = damage*(40+ 100*skill_lv)/100; break; case CH_CHAINCRUSH: // ˜A’Œ•öŒ‚ - damage = damage*(100+ 60*skill_lv)/100; - damage2 = damage2*(100+ 60*skill_lv)/100; - div_=skill_get_num(skill_num,skill_lv); + damage = damage*(400+ 100*skill_lv)/100; + damage2 = damage*(400+ 100*skill_lv)/100; break; case CH_PALMSTRIKE: // –ÒŒÕd”hŽR - damage = damage*(50+ 100*skill_lv)/100; - damage2 = damage2*(50+ 100*skill_lv)/100; + damage = damage*(200+ 100*skill_lv)/100; + damage2 = damage*(200+ 100*skill_lv)/100; break; case LK_SPIRALPIERCE: /* ƒXƒpƒCƒ‰ƒ‹ƒsƒA[ƒX */ damage = damage*(100+ 50*skill_lv)/100; //‘‰Á—Ê‚ª•ª‚©‚ç‚È‚¢‚̂œK“–‚É damage2 = damage2*(100+ 50*skill_lv)/100; //‘‰Á—Ê‚ª•ª‚©‚ç‚È‚¢‚̂œK“–‚É - div_=5; + flag=(flag&~BF_RANGEMASK)|BF_LONG; if(tsd) tsd->canmove_tick = gettick() + 1000; else if(tmd) @@ -3441,35 +2290,33 @@ static struct Damage battle_calc_pc_weapon_attack( case CG_ARROWVULCAN: /* ƒAƒ[ƒoƒ‹ƒJƒ“ */ damage = damage*(200+100*skill_lv)/100; damage2 = damage2*(200+100*skill_lv)/100; - div_=9; + if(sd->arrow_ele > 0) { + s_ele = sd->arrow_ele; + s_ele_ = sd->arrow_ele; + } + flag=(flag&~BF_RANGEMASK)|BF_LONG; break; case AS_SPLASHER: /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ[ */ damage = damage*(200+20*skill_lv+20*pc_checkskill(sd,AS_POISONREACT))/100; damage2 = damage2*(200+20*skill_lv+20*pc_checkskill(sd,AS_POISONREACT))/100; - break; - case PA_SACRIFICE: - if(sd){ - int hp, mhp, damage3; - hp = battle_get_hp(src); - mhp = battle_get_max_hp(src); - damage3 = mhp*9/100; - damage = damage*damage3*(90+10*skill_lv)/10000; - damage2 = damage2*damage3*(90+10*skill_lv)/10000; - } + no_cardfix = 1; + hitrate = 1000000; break; case ASC_BREAKER: // -- moonsoul (special damage for ASC_BREAKER skill) if(sd){ - int damage3; - int mdef1=battle_get_mdef(target); - int mdef2=battle_get_mdef2(target); - int imdef_flag=0; - - damage = ((damage * 5) + (skill_lv * battle_get_int(src) * 5) + rand()%500 + 500) /2; - damage2 = ((damage2 * 5) + (skill_lv * battle_get_int(src) * 5) + rand()%500 + 500) /2; - damage3 = damage; - hitrate = 1000000; - - if(sd->ignore_mdef_ele & (1<<t_ele) || sd->ignore_mdef_race & (1<<t_race)) + // calculate physical part of damage +#ifndef TWILIGHT + damage = damage * skill_lv; + damage2 = damage2 * skill_lv; +#else /* TWILIGHT */ + damage = damage * skill_lv * 0.5; //Halved by Krel + damage2 = damage2 * skill_lv * 0.5; //Halved by Krel + // element modifier added right after this + + // calculate magic part of damage + damage3 = skill_lv * status_get_int(src) * 5 * 0.5; //Krel + // ignores magic defense now [Celest] + /*if(sd->ignore_mdef_ele & (1<<t_ele) || sd->ignore_mdef_race & (1<<t_race)) imdef_flag = 1; if(t_mode & 0x20) { if(sd->ignore_mdef_race & (1<<10)) @@ -3487,14 +2334,23 @@ static struct Damage battle_calc_pc_weapon_attack( damage3 = (damage3*(100-mdef1))/100 - mdef2; } } - + if(damage3<1) damage3=1; - damage3=battle_attr_fix(damage2,s_ele_, battle_get_element(target) ); + damage3=battle_attr_fix(damage2,s_ele_, status_get_element(target) );*/ + +#endif /* TWILIGHT */ + flag=(flag&~BF_RANGEMASK)|BF_LONG; } break; } + if (div_flag && div_ > 1) { // [Skotlex] + damage *= div_; + damage2 *= div_; + } + if (sd && skill_num > 0 && sd->skillatk[0] == skill_num) + damage += damage*sd->skillatk[1]/100; } if(da == 2) { //ŽO’i¶‚ª”“®‚µ‚Ä‚¢‚é‚© type = 0x08; @@ -3505,20 +2361,20 @@ static struct Damage battle_calc_pc_weapon_attack( if( skill_num!=NPC_CRITICALSLASH ){ // ‘Î Û‚Ì–hŒä—͂ɂæ‚éƒ_ƒ[ƒW‚ÌŒ¸ // ƒfƒBƒoƒCƒ“ƒvƒƒeƒNƒVƒ‡ƒ“i‚±‚±‚Å‚¢‚¢‚Ì‚©‚ÈHj - if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && def1 < 1000000) { //DEF, VIT–³Ž‹ + if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && skill_num != AM_ACIDTERROR && def1 < 1000000) { //DEF, VIT–³Ž‹ int t_def; - target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penaly_count_lv); - if(battle_config.vit_penaly_type > 0) { - if(target_count >= battle_config.vit_penaly_count) { - if(battle_config.vit_penaly_type == 1) { - def1 = (def1 * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100; - def2 = (def2 * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100; - t_vit = (t_vit * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100; + target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penalty_count_lv); + if(battle_config.vit_penalty_type > 0) { + if(target_count >= battle_config.vit_penalty_count) { + if(battle_config.vit_penalty_type == 1) { + def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; + def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; + t_vit = (t_vit * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; } - else if(battle_config.vit_penaly_type == 2) { - def1 -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num; - def2 -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num; - t_vit -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num; + else if(battle_config.vit_penalty_type == 2) { + def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; + def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; + t_vit -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; } if(def1 < 0) def1 = 0; if(def2 < 1) def2 = 1; @@ -3527,6 +2383,19 @@ static struct Damage battle_calc_pc_weapon_attack( } t_def = def2*8/10; vitbonusmax = (t_vit/20)*(t_vit/20)-1; + if (tmd) { + if(t_mode & 0x20) { + if(sd->ignore_def_mob & 2) + idef_flag = 1; + if(sd->ignore_def_mob_ & 2) + idef_flag_ = 1; + } else { + if(sd->ignore_def_mob & 1) + idef_flag = 1; + if(sd->ignore_def_mob_ & 1) + idef_flag_ = 1; + } + } if(sd->ignore_def_ele & (1<<t_ele) || sd->ignore_def_race & (1<<t_race)) idef_flag = 1; if(sd->ignore_def_ele_ & (1<<t_ele) || sd->ignore_def_race_ & (1<<t_race)) @@ -3567,24 +2436,39 @@ static struct Damage battle_calc_pc_weapon_attack( // ó‘ÔˆÙí’†‚̃_ƒ[ƒW’ljÁ‚ŃNƒŠƒeƒBƒJƒ‹‚É‚à—LŒø‚ȃXƒLƒ‹ if (sc_data) { // ƒGƒ“ƒ`ƒƒƒ“ƒgƒfƒbƒhƒŠ[ƒ|ƒCƒYƒ“ - if(sc_data[SC_EDP].timer != -1) { + if(!no_cardfix && sc_data[SC_EDP].timer != -1 && skill_num != ASC_BREAKER && skill_num != ASC_METEORASSAULT) { damage += damage * (150 + sc_data[SC_EDP].val1 * 50) / 100; - damage2 += damage2 * (150 + sc_data[SC_EDP].val1 * 50) / 100; no_cardfix = 1; } + // sacrifice works on boss monsters, and does 9% damage to self [Celest] + if (!skill_num && /*!(t_mode&0x20) &&*/ sc_data[SC_SACRIFICE].timer != -1) { + int mhp = status_get_max_hp(src); + int dmg = mhp * 9/100; + pc_heal(sd, -dmg, 0); + damage = dmg * (90 + sc_data[SC_SACRIFICE].val1 * 10) / 100; + damage2 = 0; + hitrate = 1000000; + s_ele = 0; + s_ele_ = 0; + skill_num = PA_SACRIFICE; + //clif_skill_nodamage(src,target,skill_num,skill_lv,1); // this doesn't show effect either.. hmm =/ + sc_data[SC_SACRIFICE].val2 --; + if (sc_data[SC_SACRIFICE].val2 == 0) + status_change_end(src, SC_SACRIFICE,-1); + } } // ¸˜Bƒ_ƒ[ƒW‚̒ljÁ if( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST) { //DEF, VIT–³Ž‹ - damage += battle_get_atk2(src); - damage2 += battle_get_atk_2(src); + damage += status_get_atk2(src); + damage2 += status_get_atk_2(src); } if(skill_num == CR_SHIELDBOOMERANG) { if(sd->equip_index[8] >= 0) { int index = sd->equip_index[8]; if(sd->inventory_data[index] && sd->inventory_data[index]->type == 5) { damage += sd->inventory_data[index]->weight/10; - damage += sd->status.inventory[index].refine * pc_getrefinebonus(0,1); + damage += sd->status.inventory[index].refine * status_getrefinebonus(0,1); } } } @@ -3593,7 +2477,7 @@ static struct Damage battle_calc_pc_weapon_attack( int index = sd->equip_index[9]; if(sd->inventory_data[index] && sd->inventory_data[index]->type == 4) { damage += (int)(double)(sd->inventory_data[index]->weight*(0.8*skill_lv*4/10)); - damage += sd->status.inventory[index].refine * pc_getrefinebonus(0,1); + damage += sd->status.inventory[index].refine * status_getrefinebonus(0,1); } } } @@ -3617,10 +2501,10 @@ static struct Damage battle_calc_pc_weapon_attack( // ‰ñ”ðC³ if( hitrate < 1000000 && t_sc_data ) { // •K’†UŒ‚ if(t_sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG) - hitrate -= 50; + hitrate -= 75; if (t_sc_data[SC_SLEEP].timer!=-1 || // ‡–°‚Í•K’† t_sc_data[SC_STAN].timer!=-1 || // ƒXƒ^ƒ“‚Í•K’† - t_sc_data[SC_FREEZE].timer!=-1 || + t_sc_data[SC_FREEZE].timer!=-1 || (t_sc_data[SC_STONE].timer!=-1 && t_sc_data[SC_STONE].val2==0)) // “€Œ‹‚Í•K’† hitrate = 1000000; } @@ -3653,17 +2537,20 @@ static struct Damage battle_calc_pc_weapon_attack( cardfix=cardfix*(100+sd->addrace[t_race])/100; // Ží‘°‚É‚æ‚éƒ_ƒ[ƒWC³ cardfix=cardfix*(100+sd->addele[t_ele])/100; // ‘®«‚É‚æ‚éƒ_ƒ[ƒWC³ cardfix=cardfix*(100+sd->addsize[t_size])/100; // ƒTƒCƒY‚É‚æ‚éƒ_ƒ[ƒWC³ + cardfix=cardfix*(100+sd->addrace2[t_race2])/100; } else { cardfix=cardfix*(100+sd->addrace[t_race]+sd->addrace_[t_race])/100; // Ží‘°‚É‚æ‚éƒ_ƒ[ƒWC³(¶Žè‚É‚æ‚é’ljÁ‚ ‚è) cardfix=cardfix*(100+sd->addele[t_ele]+sd->addele_[t_ele])/100; // ‘®«‚É‚æ‚éƒ_ƒ[ƒWC³(¶Žè‚É‚æ‚é’ljÁ‚ ‚è) cardfix=cardfix*(100+sd->addsize[t_size]+sd->addsize_[t_size])/100; // ƒTƒCƒY‚É‚æ‚éƒ_ƒ[ƒWC³(¶Žè‚É‚æ‚é’ljÁ‚ ‚è) + cardfix=cardfix*(100+sd->addrace2[t_race2]+sd->addrace2_[t_race2])/100; } } else { //‹|–î cardfix=cardfix*(100+sd->addrace[t_race]+sd->arrow_addrace[t_race])/100; // Ží‘°‚É‚æ‚éƒ_ƒ[ƒWC³(‹|–î‚É‚æ‚é’ljÁ‚ ‚è) cardfix=cardfix*(100+sd->addele[t_ele]+sd->arrow_addele[t_ele])/100; // ‘®«‚É‚æ‚éƒ_ƒ[ƒWC³(‹|–î‚É‚æ‚é’ljÁ‚ ‚è) cardfix=cardfix*(100+sd->addsize[t_size]+sd->arrow_addsize[t_size])/100; // ƒTƒCƒY‚É‚æ‚éƒ_ƒ[ƒWC³(‹|–î‚É‚æ‚é’ljÁ‚ ‚è) + cardfix=cardfix*(100+sd->addrace2[t_race2])/100; } if(t_mode & 0x20) { //ƒ{ƒX if(!sd->state.arrow_atk) { //‹|–îUŒ‚ˆÈŠO‚È‚ç @@ -3686,7 +2573,7 @@ static struct Damage battle_calc_pc_weapon_attack( cardfix=cardfix*(100+sd->addrace[11]+sd->arrow_addrace[11])/100; //ƒ{ƒXˆÈŠOƒ‚ƒ“ƒXƒ^[‚ɒljÁƒ_ƒ[ƒW(‹|–î‚É‚æ‚é’ljÁ‚ ‚è) } //“Á’èClass—p•Ⳉ—(—‚Ì“ú‹L¨ƒ{ƒ“ƒSƒ“—pH) - t_class = battle_get_class(target); + t_class = status_get_class(target); for(i=0;i<sd->add_damage_class_count;i++) { if(sd->add_damage_classid[i] == t_class) { cardfix=cardfix*(100+sd->add_damage_classrate[i])/100; @@ -3703,6 +2590,7 @@ static struct Damage battle_calc_pc_weapon_attack( cardfix=cardfix*(100+sd->addrace_[t_race])/100; // Ží‘°‚É‚æ‚éƒ_ƒ[ƒWC³¶Žè cardfix=cardfix*(100+sd->addele_[t_ele])/100; // ‘® «‚É‚æ‚éƒ_ƒ[ƒWC³¶Žè cardfix=cardfix*(100+sd->addsize_[t_size])/100; // ƒTƒCƒY‚É‚æ‚éƒ_ƒ[ƒWC³¶Žè + cardfix=cardfix*(100+sd->addrace2_[t_race2])/100; if(t_mode & 0x20) //ƒ{ƒX cardfix=cardfix*(100+sd->addrace_[10])/100; //ƒ{ƒXƒ‚ƒ“ƒXƒ^[‚ɒljÁƒ_ƒ[ƒW¶Žè else @@ -3716,27 +2604,24 @@ static struct Damage battle_calc_pc_weapon_attack( } } if(!no_cardfix) - damage2=damage2*cardfix/100; + //ƒJ[ƒh•Ⳃɂæ‚é¶Žèƒ_ƒ[ƒW‘‰Á //ƒJ[ƒh‚É‚æ‚éƒ_ƒ[ƒW‘‰Áˆ—(¶Žè)‚±‚±‚܂Š-// -- moonsoul (cardfix for magic damage portion of ASC_BREAKER) - if(skill_num == ASC_BREAKER) - damage3 = damage3 * cardfix / 100; - //ƒJ[ƒh‚É‚æ‚éƒ_ƒ[ƒWŒ¸Šˆ—‚±‚±‚©‚ç if(tsd){ //‘ÎÛ‚ªPC‚Ìê‡ cardfix=100; cardfix=cardfix*(100-tsd->subrace[s_race])/100; // Ží‘°‚É‚æ‚éƒ_ƒ[ƒW‘Ï« cardfix=cardfix*(100-tsd->subele[s_ele])/100; // ‘®«‚É‚æ‚éƒ_ƒ[ƒW‘Ï« - if(battle_get_mode(src) & 0x20) + cardfix=cardfix*(100-tsd->subsize[s_size])/100; + if(status_get_mode(src) & 0x20) cardfix=cardfix*(100-tsd->subrace[10])/100; //ƒ{ƒX‚©‚ç‚ÌUŒ‚‚̓_ƒ[ƒWŒ¸ else cardfix=cardfix*(100-tsd->subrace[11])/100; //ƒ{ƒXˆÈŠO‚©‚ç‚ÌUŒ‚‚̓_ƒ[ƒWŒ¸ //“Á’èClass—p•Ⳉ—¶Žè(—‚Ì“ú‹L¨ƒ{ƒ“ƒSƒ“—pH) for(i=0;i<tsd->add_def_class_count;i++) { - if(tsd->add_def_classid[i] == sd->status.class) { + if(tsd->add_def_classid[i] == sd->status.class_) { cardfix=cardfix*(100-tsd->add_def_classrate[i])/100; break; } @@ -3756,29 +2641,29 @@ static struct Damage battle_calc_pc_weapon_attack( if(t_sc_data[SC_DEFENDER].timer != -1 && flag&BF_LONG) //ƒfƒBƒtƒFƒ“ƒ_[ó‘Ԃʼn“‹——£UŒ‚ cardfix=cardfix*(100-t_sc_data[SC_DEFENDER].val2)/100; //ƒfƒBƒtƒFƒ“ƒ_[‚É‚æ‚éŒ¸Š if(t_sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG) - cardfix=cardfix*(100-t_sc_data[SC_FOGWALL].val2)/100; + cardfix=cardfix*50/100; if(cardfix != 100) { damage=damage*cardfix/100; //ƒfƒBƒtƒFƒ“ƒ_[•Ⳃɂæ‚éƒ_ƒ[ƒWŒ¸ damage2=damage2*cardfix/100; //ƒfƒBƒtƒFƒ“ƒ_[•Ⳃɂæ‚é¶Žèƒ_ƒ[ƒWŒ¸ } if(t_sc_data[SC_ASSUMPTIO].timer != -1){ //ƒAƒXƒ€ƒvƒeƒBƒI if(!map[target->m].flag.pvp){ - damage=damage/3; - damage2=damage2/3; - }else{ - damage=damage/2; - damage2=damage2/2; + damage=damage/3; + damage2=damage2/3; + }else{ + damage=damage/2; + damage2=damage2/2; + } } } - } //‘ÎۂɃXƒe[ƒ^ƒXˆÙ킪‚ ‚éꇂ̃_ƒ[ƒWŒ¸ŽZˆ—‚±‚±‚܂Šif(damage < 0) damage = 0; if(damage2 < 0) damage2 = 0; // ‘® «‚Ì“K—p - damage=battle_attr_fix(damage,s_ele, battle_get_element(target) ); - damage2=battle_attr_fix(damage2,s_ele_, battle_get_element(target) ); + damage=battle_attr_fix(damage,s_ele, status_get_element(target) ); + damage2=battle_attr_fix(damage2,s_ele_, status_get_element(target) ); // ¯‚Ì‚©‚¯‚çA‹C‹…‚Ì“K—p damage += sd->star; @@ -3797,16 +2682,16 @@ static struct Damage battle_calc_pc_weapon_attack( // >“ñ“—¬‚̶‰Eƒ_ƒ[ƒWŒvŽZ’N‚©‚â‚Á‚Ä‚‚ê‚¥‚¥‚¥‚¥‚¦‚¦‚¦I // >map_session_data ‚ɶŽèƒ_ƒ[ƒW(atk,atk2)’ljÁ‚µ‚Ä - // >pc_calcstatus()‚Å‚â‚é‚ׂ«‚©‚ÈH + // >status_calc_pc()‚Å‚â‚é‚ׂ«‚©‚ÈH // map_session_data ‚ɶŽè•Ší(atk,atk2,ele,star,atkmods)’ljÁ‚µ‚Ä - // pc_calcstatus()‚Ńf[ƒ^‚ð“ü—Í‚µ‚Ä‚¢‚Ü‚· + // status_calc_pc()‚Ńf[ƒ^‚ð“ü—Í‚µ‚Ä‚¢‚Ü‚· //¶Žè‚̂ݕŠí‘•”õ if(sd->weapontype1 == 0 && sd->weapontype2 > 0) { damage = damage2; damage2 = 0; } - + // ‰EŽèA¶ŽèC—û‚Ì“K—p if(sd->status.weapon > 16) {// “ñ“—¬‚©? int dmg = damage, dmg2 = damage2; @@ -3838,14 +2723,14 @@ static struct Damage battle_calc_pc_weapon_attack( // ƒCƒ“ƒxƒiƒ€C³ if(skill_num==TF_POISON){ - damage = battle_attr_fix(damage + 15*skill_lv, s_ele, battle_get_element(target) ); + damage = battle_attr_fix(damage + 15*skill_lv, s_ele, status_get_element(target) ); } if(skill_num==MC_CARTREVOLUTION){ - damage = battle_attr_fix(damage, 0, battle_get_element(target) ); + damage = battle_attr_fix(damage, 0, status_get_element(target) ); } // Š®‘S‰ñ”ð‚Ì”»’è - if(skill_num == 0 && skill_lv >= 0 && tsd!=NULL && div_ < 255 && rand()%1000 < battle_get_flee2(target) ){ + if(skill_num == 0 && tsd!=NULL && div_ < 255 && rand()%1000 < status_get_flee2(target) ){ damage=damage2=0; type=0x0b; dmg_lv = ATK_LUCKY; @@ -3853,7 +2738,7 @@ static struct Damage battle_calc_pc_weapon_attack( // ‘ÎÛ‚ªŠ®‘S‰ñ”ð‚ð‚·‚éݒ肪ON‚È‚ç if(battle_config.enemy_perfect_flee) { - if(skill_num == 0 && skill_lv >= 0 && tmd!=NULL && div_ < 255 && rand()%1000 < battle_get_flee2(target) ) { + if(skill_num == 0 && tmd!=NULL && div_ < 255 && rand()%1000 < status_get_flee2(target) ) { damage=damage2=0; type=0x0b; dmg_lv = ATK_LUCKY; @@ -3921,21 +2806,14 @@ static struct Damage battle_calc_pc_weapon_attack( } } - -// -- moonsoul (final combination of phys, mag damage for ASC_BREAKER) - if(skill_num == ASC_BREAKER) { - damage += damage3; - damage2 += damage3; - } - wd.damage=damage; wd.damage2=damage2; wd.type=type; wd.div_=div_; - wd.amotion=battle_get_amotion(src); + wd.amotion=status_get_amotion(src); if(skill_num == KN_AUTOCOUNTER) wd.amotion >>= 1; - wd.dmotion=battle_get_dmotion(target); + wd.dmotion=status_get_dmotion(target); wd.blewcount=blewcount; wd.flag=flag; wd.dmg_lv=dmg_lv; @@ -3972,32 +2850,45 @@ struct Damage battle_calc_weapon_attack( memset(&wd,0,sizeof(wd)); if(battle_config.equipment_breaking && src->type==BL_PC && (wd.damage > 0 || wd.damage2 > 0)) { - struct map_session_data *sd=(struct map_session_data *)src; - int breakrate=1; - if(sd->status.weapon && sd->status.weapon!=11) { - if(target->type == BL_PC && sd->sc_data[SC_MELTDOWN].timer!=-1){ - breakrate+=100*sd->sc_data[SC_MELTDOWN].val1; - if(rand()%10000 < breakrate*battle_config.equipment_break_rate/100 || breakrate >= 10000) - pc_breakweapon((struct map_session_data *)target); + struct map_session_data *sd = (struct map_session_data *)src; + // weapon = 0, armor = 1 + int breakrate = 1; //0.01% default self weapon breaking chance [DracoRPG] + int breakrate_[2] = {0,0}; //enemy breaking chance [celest] + int breaktime = 5000; + + breakrate_[0] += sd->break_weapon_rate; + breakrate_[1] += sd->break_armor_rate; + + if (sd->sc_count) { + if (sd->sc_data[SC_MELTDOWN].timer!=-1) { + breakrate_[0] += 100*sd->sc_data[SC_MELTDOWN].val1; + breakrate_[1] = 70*sd->sc_data[SC_MELTDOWN].val1; + breaktime = skill_get_time2(WS_MELTDOWN,1); } if(sd->sc_data[SC_OVERTHRUST].timer!=-1) - breakrate+=20*sd->sc_data[SC_OVERTHRUST].val1; - if(wd.type==0x0a) - breakrate*=2; - if(rand()%10000 < breakrate*battle_config.equipment_break_rate/100 || breakrate >= 10000) { - if(pc_breakweapon(sd)==1) + breakrate += 10; + } + + if(sd->status.weapon && sd->status.weapon != 11) { + if(rand() % 10000 < breakrate * battle_config.equipment_break_rate / 100 || breakrate >= 10000) + if (pc_breakweapon(sd) == 1) wd = battle_calc_pc_weapon_attack(src,target,skill_num,skill_lv,wflag); - } } - } - - if (battle_config.equipment_breaking && target->type == BL_PC && (wd.damage > 0 || wd.damage2 > 0)) { - int breakrate=1; - if(src->type==BL_PC && ((struct map_session_data *)src)->sc_data[SC_MELTDOWN].timer!=-1) breakrate+=70*((struct map_session_data *)src)->sc_data[SC_MELTDOWN].val1; - if (wd.type==0x0a) - breakrate*=2; - if (rand()%10000 < breakrate*battle_config.equipment_break_rate/100 || breakrate >= 10000) { - pc_breakarmor((struct map_session_data *)target); + if(rand() % 10000 < breakrate_[0] * battle_config.equipment_break_rate / 100 || breakrate_[0] >= 10000) { + if (target->type == BL_PC) { + struct map_session_data *tsd = (struct map_session_data *)target; + if(tsd->status.weapon != 11) + pc_breakweapon(tsd); + } else + status_change_start(target,SC_STRIPWEAPON,1,75,0,0,breaktime,0); + } + if(rand() % 10000 < breakrate_[1] * battle_config.equipment_break_rate/100 || breakrate_[1] >= 10000) { + if (target->type == BL_PC) { + struct map_session_data *tsd = (struct map_session_data *)target; + if(tsd->status.weapon != 11) + pc_breakarmor(tsd); + } else + status_change_start(target,SC_STRIPSHIELD,1,75,0,0,breaktime,0); } } @@ -4011,13 +2902,14 @@ struct Damage battle_calc_weapon_attack( struct Damage battle_calc_magic_attack( struct block_list *bl,struct block_list *target,int skill_num,int skill_lv,int flag) { - int mdef1=battle_get_mdef(target); - int mdef2=battle_get_mdef2(target); + int mdef1=status_get_mdef(target); + int mdef2=status_get_mdef2(target); int matk1,matk2,damage=0,div_=1,blewcount=skill_get_blewcount(skill_num,skill_lv),rdamage = 0; struct Damage md; int aflag; int normalmagic_flag=1; - int ele=0,race=7,t_ele=0,t_race=7,t_mode = 0,cardfix,t_class,i; + int matk_flag = 1; + int ele=0,race=7,size=1,race2=7,t_ele=0,t_race=7,t_mode = 0,cardfix,t_class,i; struct map_session_data *sd=NULL,*tsd=NULL; struct mob_data *tmd = NULL; @@ -4034,13 +2926,15 @@ struct Damage battle_calc_magic_attack( return md; } - matk1=battle_get_matk1(bl); - matk2=battle_get_matk2(bl); + matk1=status_get_matk1(bl); + matk2=status_get_matk2(bl); ele = skill_get_pl(skill_num); - race = battle_get_race(bl); - t_ele = battle_get_elem_type(target); - t_race = battle_get_race(target); - t_mode = battle_get_mode(target); + race = status_get_race(bl); + size = status_get_size(bl); + race2 = status_get_race2(bl); + t_ele = status_get_elem_type(target); + t_race = status_get_race(target); + t_mode = status_get_mode(target); #define MATK_FIX( a,b ) { matk1=matk1*(a)/(b); matk2=matk2*(a)/(b); } @@ -4078,10 +2972,10 @@ struct Damage battle_calc_magic_attack( case PR_TURNUNDEAD: // UŒ‚ƒŠƒUƒŒƒNƒVƒ‡ƒ“‚ƃ^[ƒ“ƒAƒ“ƒfƒbƒh if(target->type != BL_PC && battle_check_undead(t_race,t_ele)){ int hp, mhp, thres; - hp = battle_get_hp(target); - mhp = battle_get_max_hp(target); - thres = (skill_lv * 20) + battle_get_luk(bl)+ - battle_get_int(bl) + battle_get_lv(bl)+ + hp = status_get_hp(target); + mhp = status_get_max_hp(target); + thres = (skill_lv * 20) + status_get_luk(bl)+ + status_get_int(bl) + status_get_lv(bl)+ ((200 - hp * 200 / mhp)); if(thres > 700) thres = 700; // if(battle_config.battle_log) @@ -4089,7 +2983,7 @@ struct Damage battle_calc_magic_attack( if(rand()%1000 < thres && !(t_mode&0x20)) // ¬Œ÷ damage = hp; else // ޏ”s - damage = battle_get_lv(bl) + battle_get_int(bl) + skill_lv * 10; + damage = status_get_lv(bl) + status_get_int(bl) + skill_lv * 10; } normalmagic_flag=0; break; @@ -4157,7 +3051,7 @@ struct Damage battle_calc_magic_attack( break; case WZ_STORMGUST: // ƒXƒg[ƒ€ƒKƒXƒg MATK_FIX( skill_lv*40+100 ,100 ); - blewcount|=0x10000; +// blewcount|=0x10000; break; case AL_HOLYLIGHT: // ƒz[ƒŠ[ƒ‰ƒCƒg MATK_FIX( 125,100 ); @@ -4174,15 +3068,30 @@ struct Damage battle_calc_magic_attack( printf("battle_calc_magic_attack(): napalmvulcan enemy count=0 !\n"); } break; + case PF_SOULBURN: // Celest + if (target->type != BL_PC || skill_lv < 5) { + memset(&md,0,sizeof(md)); + return md; + } else if (target->type == BL_PC) { + damage = ((struct map_session_data *)target)->status.sp * 2; + matk_flag = 0; // don't consider matk and matk2 + } + break; + case ASC_BREAKER: + damage = rand()%500 + 500 + skill_lv * status_get_int(bl) * 5; + matk_flag = 0; // don't consider matk and matk2 + break; } } if(normalmagic_flag){ // ˆê”Ê–‚–@ƒ_ƒ[ƒWŒvŽZ int imdef_flag=0; - if(matk1>matk2) - damage= matk2+rand()%(matk1-matk2+1); - else - damage= matk2; + if (matk_flag) { + if(matk1>matk2) + damage= matk2+rand()%(matk1-matk2+1); + else + damage= matk2; + } if(sd) { if(sd->ignore_mdef_ele & (1<<t_ele) || sd->ignore_mdef_race & (1<<t_race)) imdef_flag = 1; @@ -4216,7 +3125,7 @@ struct Damage battle_calc_magic_attack( cardfix=cardfix*(100+sd->magic_addrace[10])/100; else cardfix=cardfix*(100+sd->magic_addrace[11])/100; - t_class = battle_get_class(target); + t_class = status_get_class(target); for(i=0;i<sd->add_magic_damage_class_count;i++) { if(sd->add_magic_damage_classid[i] == t_class) { cardfix=cardfix*(100+sd->add_magic_damage_classrate[i])/100; @@ -4224,15 +3133,19 @@ struct Damage battle_calc_magic_attack( } } damage=damage*cardfix/100; + if (skill_num > 0 && sd->skillatk[0] == skill_num) + damage += damage*sd->skillatk[1]/100; } if( tsd ){ - int s_class = battle_get_class(bl); + int s_class = status_get_class(bl); cardfix=100; cardfix=cardfix*(100-tsd->subele[ele])/100; // ‘® «‚É‚æ‚éƒ_ƒ[ƒW‘Ï« cardfix=cardfix*(100-tsd->subrace[race])/100; // Ží‘°‚É‚æ‚éƒ_ƒ[ƒW‘Ï« + cardfix=cardfix*(100-tsd->subsize[size])/100; cardfix=cardfix*(100-tsd->magic_subrace[race])/100; - if(battle_get_mode(bl) & 0x20) + cardfix=cardfix*(100-tsd->subrace2[race2])/100; // Ží‘°‚É‚æ‚éƒ_ƒ[ƒW‘Ï« + if(status_get_mode(bl) & 0x20) cardfix=cardfix*(100-tsd->magic_subrace[10])/100; else cardfix=cardfix*(100-tsd->magic_subrace[11])/100; @@ -4247,13 +3160,13 @@ struct Damage battle_calc_magic_attack( } if(damage < 0) damage = 0; - damage=battle_attr_fix(damage, ele, battle_get_element(target) ); // ‘® «C³ + damage=battle_attr_fix(damage, ele, status_get_element(target) ); // ‘® «C³ if(skill_num == CR_GRANDCROSS) { // ƒOƒ‰ƒ“ƒhƒNƒƒX struct Damage wd; wd=battle_calc_weapon_attack(bl,target,skill_num,skill_lv,flag); damage = (damage + wd.damage) * (100 + 40*skill_lv)/100; - if(battle_config.gx_dupele) damage=battle_attr_fix(damage, ele, battle_get_element(target) ); //‘®«2‰ñ‚©‚©‚é + if(battle_config.gx_dupele) damage=battle_attr_fix(damage, ele, status_get_element(target) ); //‘®«2‰ñ‚©‚©‚é if(bl==target) damage=damage/2; //”½“®‚Í”¼•ª } @@ -4287,8 +3200,8 @@ struct Damage battle_calc_magic_attack( md.damage=damage; md.div_=div_; - md.amotion=battle_get_amotion(bl); - md.dmotion=battle_get_dmotion(target); + md.amotion=status_get_amotion(bl); + md.dmotion=status_get_dmotion(target); md.damage2=0; md.type=0; md.blewcount=blewcount; @@ -4304,16 +3217,16 @@ struct Damage battle_calc_magic_attack( struct Damage battle_calc_misc_attack( struct block_list *bl,struct block_list *target,int skill_num,int skill_lv,int flag) { - int int_=battle_get_int(bl); -// int luk=battle_get_luk(bl); - int dex=battle_get_dex(bl); - int skill,ele,race,cardfix; + int int_=status_get_int(bl); +// int luk=status_get_luk(bl); + int dex=status_get_dex(bl); + int skill,ele,race,size,cardfix,race2; struct map_session_data *sd=NULL,*tsd=NULL; int damage=0,div_=1,blewcount=skill_get_blewcount(skill_num,skill_lv); struct Damage md; int damagefix=1; - int aflag=BF_MISC|BF_LONG|BF_SKILL; + int aflag=BF_MISC|BF_SHORT|BF_SKILL; //return‘O‚̈—‚ª‚ ‚é‚Ì‚Åî•ño—Í•”‚̂ݕÏX if( bl == NULL || target == NULL ){ @@ -4355,11 +3268,13 @@ struct Damage battle_calc_misc_attack( damage=(dex/10+int_/2+skill*3+40)*2; if(flag > 1) damage /= flag; + aflag |= (flag&~BF_RANGEMASK)|BF_LONG; break; case TF_THROWSTONE: // Î“Š‚° damage=50; damagefix=0; + aflag |= (flag&~BF_RANGEMASK)|BF_LONG; break; case BA_DISSONANCE: // •s‹¦˜a‰¹ @@ -4367,7 +3282,7 @@ struct Damage battle_calc_misc_attack( break; case NPC_SELFDESTRUCTION: // Ž©”š - damage=battle_get_hp(bl)-(bl==target?1:0); + damage=status_get_hp(bl)-(bl==target?1:0); damagefix=0; break; @@ -4378,8 +3293,8 @@ struct Damage battle_calc_misc_attack( case NPC_DARKBREATH: { - struct status_change *sc_data = battle_get_sc_data(target); - int hitrate=battle_get_hit(bl) - battle_get_flee(target) + 80; + struct status_change *sc_data = status_get_sc_data(target); + int hitrate=status_get_hit(bl) - status_get_flee(target) + 80; hitrate = ( (hitrate>95)?95: ((hitrate<5)?5:hitrate) ); if(sc_data && (sc_data[SC_SLEEP].timer!=-1 || sc_data[SC_STAN].timer!=-1 || sc_data[SC_FREEZE].timer!=-1 || (sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0) ) ) @@ -4391,13 +3306,25 @@ struct Damage battle_calc_misc_attack( } break; case SN_FALCONASSAULT: /* ƒtƒ@ƒ‹ƒRƒ“ƒAƒTƒ‹ƒg */ - skill = pc_checkskill(sd,HT_STEELCROW); // Celest - damage=((150+50*skill_lv)*(dex/10+int_/2+skill*3+40)*2)/100; +#ifdef TWILIGHT + if( sd==NULL || (skill = pc_checkskill(sd,HT_BLITZBEAT)) <= 0) + skill=0; + damage=(100+50*skill_lv+(dex/10+int_/2+skill*3+40)*2) * 2; +#else + if( sd==NULL || (skill = pc_checkskill(sd,HT_STEELCROW)) <= 0) + skill=0; + damage=((150+50*skill_lv)*(dex/10+int_/2+skill*3+40)*2)/100; // [Celest] +#endif + if(flag > 1) + damage /= flag; + aflag |= (flag&~BF_RANGEMASK)|BF_LONG; break; } ele = skill_get_pl(skill_num); - race = battle_get_race(bl); + race = status_get_race(bl); + size = status_get_size(bl); + race2 = status_get_race(bl); if(damagefix){ if(damage<1 && skill_num != NPC_DARKBREATH) @@ -4407,27 +3334,35 @@ struct Damage battle_calc_misc_attack( cardfix=100; cardfix=cardfix*(100-tsd->subele[ele])/100; // ‘®«‚É‚æ‚éƒ_ƒ[ƒW‘Ï« cardfix=cardfix*(100-tsd->subrace[race])/100; // Ží‘°‚É‚æ‚éƒ_ƒ[ƒW‘Ï« + cardfix=cardfix*(100-tsd->subsize[size])/100; cardfix=cardfix*(100-tsd->misc_def_rate)/100; + cardfix=cardfix*(100-tsd->subrace2[race2])/100; damage=damage*cardfix/100; } + if (sd && skill_num > 0 && sd->skillatk[0] == skill_num) + damage += damage*sd->skillatk[1]/100; + if(damage < 0) damage = 0; - damage=battle_attr_fix(damage, ele, battle_get_element(target) ); // ‘®«C³ + damage=battle_attr_fix(damage, ele, status_get_element(target) ); // ‘®«C³ } div_=skill_get_num( skill_num,skill_lv ); if(div_>1) damage*=div_; - if(damage > 0 && (damage < div_ || (battle_get_def(target) >= 1000000 && battle_get_mdef(target) >= 1000000) ) ) { + if(damage > 0 && (damage < div_ || (status_get_def(target) >= 1000000 && status_get_mdef(target) >= 1000000) ) ) { damage = div_; } + if(status_get_mode(target)&0x40 && damage>0) + damage = 1; + damage=battle_calc_damage(bl,target,damage,div_,skill_num,skill_lv,aflag); // ÅIC³ md.damage=damage; md.div_=div_; - md.amotion=battle_get_amotion(bl); - md.dmotion=battle_get_dmotion(target); + md.amotion=status_get_amotion(bl); + md.dmotion=status_get_dmotion(target); md.damage2=0; md.type=0; md.blewcount=blewcount; @@ -4453,6 +3388,7 @@ struct Damage battle_calc_attack( int attack_type, default: if(battle_config.error_log) printf("battle_calc_attack: unknwon attack type ! %d\n",attack_type); + memset(&d,0,sizeof(d)); break; } return d; @@ -4465,7 +3401,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, unsigned int tick,int flag) { struct map_session_data *sd=NULL; - struct status_change *sc_data = battle_get_sc_data(src),*t_sc_data=battle_get_sc_data(target); + struct status_change *sc_data = status_get_sc_data(src),*t_sc_data=status_get_sc_data(target); short *opt1; int race = 7, ele = 0; int damage,rdamage = 0; @@ -4484,7 +3420,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, if(target->type == BL_PC && pc_isdead((struct map_session_data *)target)) return 0; - opt1=battle_get_opt1(src); + opt1=status_get_opt1(src); if(opt1 && *opt1 > 0) { battle_stopattack(src); return 0; @@ -4495,11 +3431,11 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, } if(battle_check_target(src,target,BCT_ENEMY) <= 0 && - !battle_check_range(src,target,0)) + !battle_check_range(src,target,0)) return 0; // UŒ‚‘ÎÛŠO - race = battle_get_race(target); - ele = battle_get_elem_type(target); + race = status_get_race(target); + ele = status_get_elem_type(target); if(battle_check_target(src,target,BCT_ENEMY) > 0 && battle_check_range(src,target,0)){ // UŒ‚‘ÎۂƂȂ肤‚é‚Ì‚ÅUŒ‚ @@ -4549,17 +3485,17 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, } } if(rdamage > 0) - clif_damage(src,src,tick, wd.amotion,0,rdamage,1,4,0); + clif_damage(src,src,tick,wd.amotion,wd.dmotion,rdamage,1,4,0); } if (wd.div_ == 255 && sd) { //ŽO’i¶ - int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src); + int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src); int skilllv; - if(wd.damage+wd.damage2 < battle_get_hp(target)) { + if(wd.damage+wd.damage2 < status_get_hp(target)) { if((skilllv = pc_checkskill(sd, MO_CHAINCOMBO)) > 0) delay += 300 * battle_config.combo_delay_rate /100; //’ljÁƒfƒBƒŒƒC‚ðconf‚É‚æ‚è’²® - skill_status_change_start(src,SC_COMBO,MO_TRIPLEATTACK,skilllv,0,0,delay,0); + status_change_start(src,SC_COMBO,MO_TRIPLEATTACK,skilllv,0,0,delay,0); } sd->attackabletime = sd->canmove_tick = tick + delay; clif_combo_delay(src,delay); @@ -4576,23 +3512,23 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, if(sd && sd->splash_range > 0 && (wd.damage > 0 || wd.damage2 > 0) ) skill_castend_damage_id(src,target,0,-1,tick,0); map_freeblock_lock(); - battle_damage(src,target,(wd.damage+wd.damage2),0); + battle_delay_damage(tick+wd.amotion,src,target,(wd.damage+wd.damage2),0); if(target->prev != NULL && (target->type != BL_PC || (target->type == BL_PC && !pc_isdead((struct map_session_data *)target) ) ) ) { if(wd.damage > 0 || wd.damage2 > 0) { skill_additional_effect(src,target,0,0,BF_WEAPON,tick); if(sd) { if(sd->weapon_coma_ele[ele] > 0 && rand()%10000 < sd->weapon_coma_ele[ele]) - battle_damage(src,target,battle_get_max_hp(target),1); + battle_damage(src,target,status_get_max_hp(target),1); if(sd->weapon_coma_race[race] > 0 && rand()%10000 < sd->weapon_coma_race[race]) - battle_damage(src,target,battle_get_max_hp(target),1); - if(battle_get_mode(target) & 0x20) { + battle_damage(src,target,status_get_max_hp(target),1); + if(status_get_mode(target) & 0x20) { if(sd->weapon_coma_race[10] > 0 && rand()%10000 < sd->weapon_coma_race[10]) - battle_damage(src,target,battle_get_max_hp(target),1); + battle_damage(src,target,status_get_max_hp(target),1); } else { if(sd->weapon_coma_race[11] > 0 && rand()%10000 < sd->weapon_coma_race[11]) - battle_damage(src,target,battle_get_max_hp(target),1); + battle_damage(src,target,status_get_max_hp(target),1); } } } @@ -4643,69 +3579,96 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, } } if(sd) { - if(sd->autospell_id > 0 && sd->autospell_lv > 0 && rand()%100 < sd->autospell_rate) { - int skilllv=sd->autospell_lv,i,f=0,sp; + if(sd->autospell_id > 0 && rand()%100 < sd->autospell_rate) { + int skilllv = sd->autospell_lv, i; i = rand()%100; if(i >= 50) skilllv -= 2; else if(i >= 15) skilllv--; if(skilllv < 1) skilllv = 1; - sp = skill_get_sp(sd->autospell_id,skilllv)*2/3; - if(sd->status.sp >= sp) { - if((i=skill_get_inf(sd->autospell_id) == 2) || i == 32) - f = skill_castend_pos2(src,target->x,target->y,sd->autospell_id,skilllv,tick,flag); - else { - switch( skill_get_nk(sd->autospell_id) ) { - case 0: case 2: - f = skill_castend_damage_id(src,target,sd->autospell_id,skilllv,tick,flag); - break; - case 1:/* Žx‰‡Œn */ - if((sd->autospell_id==AL_HEAL || (sd->autospell_id==ALL_RESURRECTION && target->type != BL_PC)) && battle_check_undead(race,ele)) - f = skill_castend_damage_id(src,target,sd->autospell_id,skilllv,tick,flag); - else - f = skill_castend_nodamage_id(src,target,sd->autospell_id,skilllv,tick,flag); - break; - } + + if((i=skill_get_inf(sd->autospell_id) == 2) || i == 32) + skill_castend_pos2(src,target->x,target->y,sd->autospell_id,skilllv,tick,flag); + else { + switch( skill_get_nk(sd->autospell_id) ) { + case 0: case 2: + skill_castend_damage_id(src,target,sd->autospell_id,skilllv,tick,flag); + break; + case 1:/* Žx‰‡Œn */ + if((sd->autospell_id==AL_HEAL || (sd->autospell_id==ALL_RESURRECTION && target->type != BL_PC)) && battle_check_undead(race,ele)) + skill_castend_damage_id(src,target,sd->autospell_id,skilllv,tick,flag); + else + skill_castend_nodamage_id(src,target,sd->autospell_id,skilllv,tick,flag); + break; } - if(!f) pc_heal(sd,0,-sp); - } + } } - if(wd.flag&BF_WEAPON && src != target && (wd.damage > 0 || wd.damage2 > 0)) { + if (wd.flag&BF_WEAPON && src != target && (wd.damage > 0 || wd.damage2 > 0)) { int hp = 0,sp = 0; - if(sd->hp_drain_rate && sd->hp_drain_per > 0 && wd.damage > 0 && rand()%100 < sd->hp_drain_rate) { - hp += (wd.damage * sd->hp_drain_per)/100; - if(sd->hp_drain_rate > 0 && hp < 1) hp = 1; - else if(sd->hp_drain_rate < 0 && hp > -1) hp = -1; - } - if(sd->hp_drain_rate_ && sd->hp_drain_per_ > 0 && wd.damage2 > 0 && rand()%100 < sd->hp_drain_rate_) { - hp += (wd.damage2 * sd->hp_drain_per_)/100; - if(sd->hp_drain_rate_ > 0 && hp < 1) hp = 1; - else if(sd->hp_drain_rate_ < 0 && hp > -1) hp = -1; - } - if(sd->sp_drain_rate && sd->sp_drain_per > 0 && wd.damage > 0 && rand()%100 < sd->sp_drain_rate) { - sp += (wd.damage * sd->sp_drain_per)/100; - if(sd->sp_drain_rate > 0 && sp < 1) sp = 1; - else if(sd->sp_drain_rate < 0 && sp > -1) sp = -1; + if (!battle_config.left_cardfix_to_right) { // “ñ“—¬¶ŽèƒJ[ƒh‚Ì‹zŽûŒnŒø‰Ê‚ð‰EŽè‚ɒljÁ‚µ‚È‚¢ê‡ + hp += battle_calc_drain(wd.damage, sd->hp_drain_rate, sd->hp_drain_per, sd->hp_drain_value); + hp += battle_calc_drain(wd.damage2, sd->hp_drain_rate_, sd->hp_drain_per_, sd->hp_drain_value_); + sp += battle_calc_drain(wd.damage, sd->sp_drain_rate, sd->sp_drain_per, sd->sp_drain_value); + sp += battle_calc_drain(wd.damage2, sd->sp_drain_rate_, sd->sp_drain_per_, sd->sp_drain_value_); + } else { // “ñ“—¬¶ŽèƒJ[ƒh‚Ì‹zŽûŒnŒø‰Ê‚ð‰EŽè‚ɒljÁ‚·‚éê‡ + int hp_drain_rate = sd->hp_drain_rate + sd->hp_drain_rate_; + int hp_drain_per = sd->hp_drain_per + sd->hp_drain_per_; + int hp_drain_value = sd->hp_drain_value + sd->hp_drain_value_; + int sp_drain_rate = sd->sp_drain_rate + sd->sp_drain_rate_; + int sp_drain_per = sd->sp_drain_per + sd->sp_drain_per_; + int sp_drain_value = sd->sp_drain_value + sd->sp_drain_value_; + hp += battle_calc_drain(wd.damage, hp_drain_rate, hp_drain_per, hp_drain_value); + sp += battle_calc_drain(wd.damage, sp_drain_rate, sp_drain_per, sp_drain_value); } - if(sd->sp_drain_rate_ && sd->sp_drain_per_ > 0 && wd.damage2 > 0 && rand()%100 < sd->sp_drain_rate_) { - sp += (wd.damage2 * sd->sp_drain_per_)/100; - if(sd->sp_drain_rate_ > 0 && sp < 1) sp = 1; - else if(sd->sp_drain_rate_ < 0 && sp > -1) sp = -1; - } - if(hp || sp) pc_heal(sd,hp,sp); + + if (hp || sp) pc_heal(sd, hp, sp); + if (sd->sp_drain_type && target->type == BL_PC) + battle_heal(NULL,target,0,-sp,0); + } + } + if (target->type == BL_PC) { + struct map_session_data *tsd = (struct map_session_data *)target; + if(tsd && ((sd && !sd->state.arrow_atk) || (status_get_range(src)<=2)) && + tsd->autospell2_id > 0 && rand()%100 < tsd->autospell2_rate) { + struct block_list *tbl; + int skilllv = tsd->autospell_lv, i; + i = rand()%100; + if(i >= 50) skilllv -= 2; + else if(i >= 15) skilllv--; + if(skilllv < 1) skilllv = 1; + + if (tsd->autospell2_type == 0) tbl = target; + else tbl = src; + if((i=skill_get_inf(tsd->autospell2_id) == 2) || i == 32) + skill_castend_pos2(target,tbl->x,tbl->y,tsd->autospell2_id,skilllv,tick,flag); + else { + switch( skill_get_nk(tsd->autospell2_id) ) { + case 0: case 2: + skill_castend_damage_id(target,tbl,tsd->autospell2_id,skilllv,tick,flag); + break; + case 1:/* Žx‰‡Œn */ + if((tsd->autospell2_id==AL_HEAL || (tsd->autospell2_id==ALL_RESURRECTION && tbl->type != BL_PC)) && + battle_check_undead(status_get_race(tbl),status_get_elem_type(tbl))) + skill_castend_damage_id(target,tbl,tsd->autospell2_id,skilllv,tick,flag); + else + skill_castend_nodamage_id(target,tbl,tsd->autospell2_id,skilllv,tick,flag); + break; + } + } } } if(rdamage > 0) - battle_damage(target,src,rdamage,0); + battle_delay_damage(tick+wd.amotion,target,src,rdamage,0); + if(t_sc_data && t_sc_data[SC_AUTOCOUNTER].timer != -1 && t_sc_data[SC_AUTOCOUNTER].val4 > 0) { if(t_sc_data[SC_AUTOCOUNTER].val3 == src->id) battle_weapon_attack(target,src,tick,0x8000|t_sc_data[SC_AUTOCOUNTER].val1); - skill_status_change_end(target,SC_AUTOCOUNTER,-1); + status_change_end(target,SC_AUTOCOUNTER,-1); } if(t_sc_data && t_sc_data[SC_POISONREACT].timer != -1 && t_sc_data[SC_POISONREACT].val4 > 0) { // poison react [Celest] if(t_sc_data[SC_POISONREACT].val3 == src->id) { struct map_session_data *tsd = (struct map_session_data *)target; - if ((src->type == BL_MOB && battle_get_elem_type(src)==5) || (src->type == BL_PC && battle_get_attack_element(src)==5)) { + if ((src->type == BL_MOB && status_get_elem_type(src)==5) || (src->type == BL_PC && status_get_attack_element(src)==5)) { t_sc_data[SC_POISONREACT].val2 = 0; battle_weapon_attack(target,src,tick,flag|AS_POISONREACT); } else { @@ -4713,19 +3676,18 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, --t_sc_data[SC_POISONREACT].val2; } if (t_sc_data[SC_POISONREACT].val2<=0) - skill_status_change_end(target,SC_POISONREACT,-1); - } - } - if(t_sc_data && t_sc_data[SC_BLADESTOP_WAIT].timer != -1){ - if (!(src->type == BL_MOB && mob_db[((struct mob_data *)src)->class].mode&0x20)) { - int lv = t_sc_data[SC_BLADESTOP_WAIT].val1; - skill_status_change_end(target,SC_BLADESTOP_WAIT,-1); - skill_status_change_start(src,SC_BLADESTOP,lv,1,(int)src,(int)target,skill_get_time2(MO_BLADESTOP,lv),0); - skill_status_change_start(target,SC_BLADESTOP,lv,2,(int)target,(int)src,skill_get_time2(MO_BLADESTOP,lv),0); + status_change_end(target,SC_POISONREACT,-1); } } + if (t_sc_data && t_sc_data[SC_BLADESTOP_WAIT].timer != -1 && + !(status_get_mode(src)&0x20)) { // ƒ{ƒX‚ɂ͖³Œø + int lv = t_sc_data[SC_BLADESTOP_WAIT].val1; + status_change_end(target,SC_BLADESTOP_WAIT,-1); + status_change_start(src,SC_BLADESTOP,lv,1,(int)src,(int)target,skill_get_time2(MO_BLADESTOP,lv),0); + status_change_start(target,SC_BLADESTOP,lv,2,(int)target,(int)src,skill_get_time2(MO_BLADESTOP,lv),0); + } if(t_sc_data && t_sc_data[SC_SPLASHER].timer!=-1) //‰£‚Á‚½‚̂őÎۂ̃xƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ[ó‘Ô‚ð‰ðœ - skill_status_change_end(target,SC_SPLASHER,-1); + status_change_end(target,SC_SPLASHER,-1); map_freeblock_unlock(); } @@ -4789,8 +3751,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f return -1; // Celest - sc_data = battle_get_sc_data(src); - tsc_data = battle_get_sc_data(target); + sc_data = status_get_sc_data(src); + tsc_data = status_get_sc_data(target); if ((sc_data && sc_data[SC_BASILICA].timer != -1) || (tsc_data && tsc_data[SC_BASILICA].timer != -1)) return -1; @@ -4810,15 +3772,22 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f // ƒXƒLƒ‹ƒ†ƒjƒbƒg‚Ìê‡Ae‚ð‹‚ß‚é if( src->type==BL_SKILL) { - int inf2 = skill_get_inf2(((struct skill_unit *)src)->group->skill_id); - if( (ss=map_id2bl( ((struct skill_unit *)src)->group->src_id))==NULL ) + struct skill_unit *su = (struct skill_unit *)src; + int skillid, inf2; + + nullpo_retr (-1, su); + nullpo_retr (-1, su->group); + skillid = su->group->skill_id; + inf2 = skill_get_inf2(skillid); + if( (ss=map_id2bl( su->group->src_id))==NULL ) return -1; if(ss->prev == NULL) return -1; - if(inf2&0x80 && - (map[src->m].flag.pvp || pc_iskiller((struct map_session_data *)src, (struct map_session_data *)target)) && // [MouseJstr] - !(target->type == BL_PC && pc_isinvisible((struct map_session_data *)target))) - return 0; + if(inf2&0x80 && + (map[src->m].flag.pvp || + (skillid >= 115 && skillid <= 125 && map[src->m].flag.gvg)) && + !(target->type == BL_PC && pc_isinvisible((struct map_session_data *)target))) + return 0; if(ss == target) { if(inf2&0x100) return 0; @@ -4826,10 +3795,33 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f return -1; } } - // Mob‚Åmaster_id‚ª‚ ‚Á‚Äspecial_mob_ai‚È‚çA¢Š«Žå‚ð‹‚ß‚é + if( src->type==BL_MOB ){ struct mob_data *md=(struct mob_data *)src; - if(md && md->master_id>0){ + nullpo_retr (-1, md); + + if(target->type == BL_PC) { + struct map_session_data *sd = (struct map_session_data *)target; + nullpo_retr (-1, sd); + + if(md->class_ >= 1285 && md->class_ <= 1287){ + struct guild_castle *gc = guild_mapname2gc (map[target->m].name); + if(gc && agit_flag==0) // Guardians will not attack during non-woe time [Valaris] + return 1; // end addition [Valaris] + if(gc && sd->status.guild_id > 0) { + struct guild *g=guild_search(sd->status.guild_id); // don't attack guild members [Valaris] + if(g && g->guild_id == gc->guild_id) + return 1; + if(g && guild_isallied(g,gc)) + return 1; + } + } + // option to have monsters ignore GMs [Valaris] + if (battle_config.monsters_ignore_gm > 0 && pc_isGM(sd) >= battle_config.monsters_ignore_gm) + return 1; + } + // Mob‚Åmaster_id‚ª‚ ‚Á‚Äspecial_mob_ai‚È‚çA¢Š«Žå‚ð‹‚ß‚é + if(md->master_id>0){ if(md->master_id==target->id) // Žå‚È‚çm’è return 1; if(md->state.special_mob_ai){ @@ -4869,11 +3861,11 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f if(ss->type == BL_PET && target->type==BL_MOB) return 0; - s_p=battle_get_party_id(ss); - s_g=battle_get_guild_id(ss); + s_p=status_get_party_id(ss); + s_g=status_get_guild_id(ss); - t_p=battle_get_party_id(target); - t_g=battle_get_guild_id(target); + t_p=status_get_party_id(target); + t_g=status_get_guild_id(target); if(flag&0x10000) { if(s_p && t_p && s_p == t_p) // “¯‚¶ƒp[ƒeƒB‚È‚çm’èi–¡•ûj @@ -4896,7 +3888,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f if(su && su->group->target_flag==BCT_NOENEMY) return 1; else if (battle_config.pk_mode && - (((struct map_session_data*)ss)->status.class==0 || ((struct map_session_data*)target)->status.class==0 || + (((struct map_session_data*)ss)->status.class_==0 || ((struct map_session_data*)target)->status.class_==0 || ((struct map_session_data*)ss)->status.base_level < battle_config.pk_min_level || ((struct map_session_data*)target)->status.base_level < battle_config.pk_min_level)) return 1; // prevent novice engagement in pk_mode [Valaris] @@ -4939,7 +3931,6 @@ int battle_check_range(struct block_list *src,struct block_list *bl,int range) { int dx,dy; - struct walkpath_data wpd; int arange; nullpo_retr(0, src); @@ -4962,16 +3953,7 @@ int battle_check_range(struct block_list *src,struct block_list *bl,int range) // return 1; // áŠQ•¨”»’è - wpd.path_len=0; - wpd.path_pos=0; - wpd.path_half=0; - if(path_search(&wpd,src->m,src->x,src->y,bl->x,bl->y,0x10001)!=-1) - return 1; - - dx=(dx>0)?1:((dx<0)?-1:0); - dy=(dy>0)?1:((dy<0)?-1:0); - return (path_search(&wpd,src->m,src->x+dx,src->y+dy, - bl->x-dx,bl->y-dy,0x10001)!=-1)?1:0; + return path_search_long(NULL,src->m,src->x,src->y,bl->x,bl->y); } /*========================================== @@ -4989,7 +3971,7 @@ int battle_config_switch(const char *str) { static const struct { char str[128]; - int *val; + void *val; } battle_data[] = { { "warp_point_debug", &battle_config.warp_point_debug }, { "enemy_critical", &battle_config.enemy_critical }, @@ -5045,7 +4027,6 @@ static const struct { { "player_skillup_limit", &battle_config.skillup_limit }, { "weapon_produce_rate", &battle_config.wp_rate }, { "potion_produce_rate", &battle_config.pp_rate }, - { "deadly_potion_produce_rate", &battle_config.cdp_rate }, { "monster_active_enable", &battle_config.monster_active_enable }, { "monster_damage_delay_rate", &battle_config.monster_damage_delay_rate}, { "monster_loot_type", &battle_config.monster_loot_type }, @@ -5082,6 +4063,11 @@ static const struct { { "natural_heal_skill_interval", &battle_config.natural_heal_skill_interval}, { "natural_heal_weight_rate", &battle_config.natural_heal_weight_rate }, { "item_name_override_grffile", &battle_config.item_name_override_grffile}, + { "item_equip_override_grffile", &battle_config.item_equip_override_grffile}, // [Celest] + { "item_slots_override_grffile", &battle_config.item_slots_override_grffile}, // [Celest] + { "indoors_override_grffile", &battle_config.indoors_override_grffile}, // [Celest] + { "skill_sp_override_grffile", &battle_config.skill_sp_override_grffile}, // [Celest] + { "cardillust_read_grffile", &battle_config.cardillust_read_grffile}, // [Celest] { "arrow_decrement", &battle_config.arrow_decrement }, { "max_aspd", &battle_config.max_aspd }, { "max_hp", &battle_config.max_hp }, @@ -5099,14 +4085,14 @@ static const struct { { "undead_detect_type", &battle_config.undead_detect_type }, { "player_auto_counter_type", &battle_config.pc_auto_counter_type }, { "monster_auto_counter_type", &battle_config.monster_auto_counter_type}, - { "agi_penaly_type", &battle_config.agi_penaly_type }, - { "agi_penaly_count", &battle_config.agi_penaly_count }, - { "agi_penaly_num", &battle_config.agi_penaly_num }, - { "agi_penaly_count_lv", &battle_config.agi_penaly_count_lv }, - { "vit_penaly_type", &battle_config.vit_penaly_type }, - { "vit_penaly_count", &battle_config.vit_penaly_count }, - { "vit_penaly_num", &battle_config.vit_penaly_num }, - { "vit_penaly_count_lv", &battle_config.vit_penaly_count_lv }, + { "agi_penalty_type", &battle_config.agi_penalty_type }, + { "agi_penalty_count", &battle_config.agi_penalty_count }, + { "agi_penalty_num", &battle_config.agi_penalty_num }, + { "agi_penalty_count_lv", &battle_config.agi_penalty_count_lv }, + { "vit_penalty_type", &battle_config.vit_penalty_type }, + { "vit_penalty_count", &battle_config.vit_penalty_count }, + { "vit_penalty_num", &battle_config.vit_penalty_num }, + { "vit_penalty_count_lv", &battle_config.vit_penalty_count_lv }, { "player_defense_type", &battle_config.player_defense_type }, { "monster_defense_type", &battle_config.monster_defense_type }, { "pet_defense_type", &battle_config.pet_defense_type }, @@ -5127,7 +4113,7 @@ static const struct { { "monster_attack_direction_change", &battle_config.monster_attack_direction_change }, { "player_land_skill_limit", &battle_config.pc_land_skill_limit }, { "monster_land_skill_limit", &battle_config.monster_land_skill_limit}, - { "party_skill_penaly", &battle_config.party_skill_penaly }, + { "party_skill_penalty", &battle_config.party_skill_penalty }, { "monster_class_change_full_recover", &battle_config.monster_class_change_full_recover }, { "produce_item_name_input", &battle_config.produce_item_name_input }, { "produce_potion_name_input", &battle_config.produce_potion_name_input}, @@ -5140,7 +4126,6 @@ static const struct { { "dead_branch_active", &battle_config.dead_branch_active }, { "vending_max_value", &battle_config.vending_max_value }, { "show_steal_in_same_party", &battle_config.show_steal_in_same_party }, - { "enable_upper_class", &battle_config.enable_upper_class }, { "pet_attack_attr_none", &battle_config.pet_attack_attr_none }, { "mob_attack_attr_none", &battle_config.mob_attack_attr_none }, { "mob_ghostring_fix", &battle_config.mob_ghostring_fix }, @@ -5156,8 +4141,15 @@ static const struct { { "invite_request_check", &battle_config.invite_request_check }, { "skill_removetrap_type", &battle_config.skill_removetrap_type }, { "disp_experience", &battle_config.disp_experience }, - { "castle_defense_rate", &battle_config.castle_defense_rate }, - { "riding_weight", &battle_config.riding_weight }, + { "castle_defense_rate", &battle_config.castle_defense_rate }, + { "hp_rate", &battle_config.hp_rate }, + { "sp_rate", &battle_config.sp_rate }, + { "gm_can_drop_lv", &battle_config.gm_can_drop_lv }, + { "disp_hpmeter", &battle_config.disp_hpmeter }, + { "bone_drop", &battle_config.bone_drop }, + { "monster_damage_delay", &battle_config.monster_damage_delay }, + +// eAthena additions { "item_rate_common", &battle_config.item_rate_common }, // Added by RoVeRT { "item_rate_equip", &battle_config.item_rate_equip }, { "item_rate_card", &battle_config.item_rate_card }, // End Addition @@ -5198,16 +4190,23 @@ static const struct { { "max_cloth_color", &battle_config.max_cloth_color }, // added by [MouseJstr] { "castrate_dex_scale", &battle_config.castrate_dex_scale }, // added by [MouseJstr] { "area_size", &battle_config.area_size }, // added by [MouseJstr] - { "muting_players", &battle_config.muting_players}, // added by [Apple] + { "muting_players", &battle_config.muting_players}, // added by [Apple] { "zeny_from_mobs", &battle_config.zeny_from_mobs}, // [Valaris] { "mobs_level_up", &battle_config.mobs_level_up}, // [Valaris] { "pk_min_level", &battle_config.pk_min_level}, // [celest] { "skill_steal_type", &battle_config.skill_steal_type}, // [celest] { "skill_steal_rate", &battle_config.skill_steal_rate}, // [celest] { "night_darkness_level", &battle_config.night_darkness_level}, // [celest] + { "motd_type", &battle_config.motd_type}, // [celest] + { "allow_atcommand_when_mute", &battle_config.allow_atcommand_when_mute}, // [celest] + { "finding_ore_rate", &battle_config.finding_ore_rate}, // [celest] + { "exp_calc_type", &battle_config.exp_calc_type}, // [celest] + { "min_skill_delay_limit", &battle_config.min_skill_delay_limit}, // [celest] + { "require_glory_guild", &battle_config.require_glory_guild}, // [celest] + { "idle_no_share", &battle_config.idle_no_share}, // [celest], for a feature by [MouseJstr] //SQL-only options start -#ifndef TXT_ONLY +#ifndef TXT_ONLY { "mail_system", &battle_config.mail_system }, // added by [Valaris] //SQL-only options end #endif @@ -5217,7 +4216,7 @@ int battle_set_value(char *w1, char *w2) { int i; for(i = 0; i < sizeof(battle_data) / (sizeof(battle_data[0])); i++) if (strcmpi(w1, battle_data[i].str) == 0) { - *battle_data[i].val = battle_config_switch(w2); + *((unsigned int *) battle_data[i].val) = battle_config_switch(w2); return 1; } return 0; @@ -5276,7 +4275,6 @@ void battle_set_defaults() { battle_config.skillup_limit = 0; battle_config.wp_rate=100; battle_config.pp_rate=100; - battle_config.cdp_rate=100; battle_config.monster_active_enable=1; battle_config.monster_damage_delay_rate=100; battle_config.monster_loot_type=0; @@ -5313,6 +4311,11 @@ void battle_set_defaults() { battle_config.natural_heal_skill_interval=10000; battle_config.natural_heal_weight_rate=50; battle_config.item_name_override_grffile=1; + battle_config.item_equip_override_grffile=0; // [Celest] + battle_config.item_slots_override_grffile=0; // [Celest] + battle_config.indoors_override_grffile=0; // [Celest] + battle_config.skill_sp_override_grffile=0; // [Celest] + battle_config.cardillust_read_grffile=0; // [Celest] battle_config.arrow_decrement=1; battle_config.max_aspd = 199; battle_config.max_hp = 32500; @@ -5330,14 +4333,14 @@ void battle_set_defaults() { battle_config.undead_detect_type = 0; battle_config.pc_auto_counter_type = 1; battle_config.monster_auto_counter_type = 1; - battle_config.agi_penaly_type = 0; - battle_config.agi_penaly_count = 3; - battle_config.agi_penaly_num = 0; - battle_config.agi_penaly_count_lv = ATK_FLEE; - battle_config.vit_penaly_type = 0; - battle_config.vit_penaly_count = 3; - battle_config.vit_penaly_num = 0; - battle_config.vit_penaly_count_lv = ATK_DEF; + battle_config.agi_penalty_type = 0; + battle_config.agi_penalty_count = 3; + battle_config.agi_penalty_num = 0; + battle_config.agi_penalty_count_lv = ATK_FLEE; + battle_config.vit_penalty_type = 0; + battle_config.vit_penalty_count = 3; + battle_config.vit_penalty_num = 0; + battle_config.vit_penalty_count_lv = ATK_DEF; battle_config.player_defense_type = 0; battle_config.monster_defense_type = 0; battle_config.pet_defense_type = 0; @@ -5349,17 +4352,16 @@ void battle_set_defaults() { battle_config.pc_cloak_check_type = 0; battle_config.monster_cloak_check_type = 0; battle_config.gvg_short_damage_rate = 100; - battle_config.gvg_long_damage_rate = 100; - battle_config.gvg_magic_damage_rate = 100; - battle_config.gvg_misc_damage_rate = 100; + battle_config.gvg_long_damage_rate = 60; + battle_config.gvg_magic_damage_rate = 50; + battle_config.gvg_misc_damage_rate = 60; battle_config.gvg_eliminate_time = 7000; battle_config.mob_changetarget_byskill = 0; battle_config.pc_attack_direction_change = 1; battle_config.monster_attack_direction_change = 1; - battle_config.pc_undead_nofreeze = 0; battle_config.pc_land_skill_limit = 1; battle_config.monster_land_skill_limit = 1; - battle_config.party_skill_penaly = 1; + battle_config.party_skill_penalty = 1; battle_config.monster_class_change_full_recover = 0; battle_config.produce_item_name_input = 1; battle_config.produce_potion_name_input = 1; @@ -5372,7 +4374,6 @@ void battle_set_defaults() { battle_config.dead_branch_active = 0; battle_config.vending_max_value = 10000000; battle_config.show_steal_in_same_party = 0; - battle_config.enable_upper_class = 0; battle_config.pet_attack_attr_none = 0; battle_config.pc_attack_attr_none = 0; battle_config.mob_attack_attr_none = 1; @@ -5388,6 +4389,15 @@ void battle_set_defaults() { battle_config.invite_request_check = 1; battle_config.skill_removetrap_type = 0; battle_config.disp_experience = 0; + battle_config.castle_defense_rate = 100; + battle_config.hp_rate = 100; + battle_config.sp_rate = 100; + battle_config.gm_can_drop_lv = 0; + battle_config.disp_hpmeter = 0; + battle_config.bone_drop = 0; + battle_config.monster_damage_delay = 1; + +// eAthena additions battle_config.item_rate_common = 100; battle_config.item_rate_equip = 100; battle_config.item_rate_card = 100; @@ -5421,7 +4431,7 @@ void battle_set_defaults() { battle_config.ban_spoof_namer = 5; // added by [Yor] (default: 5 minutes) battle_config.hack_info_GM_level = 60; // added by [Yor] (default: 60, GM level) battle_config.any_warp_GM_min_level = 20; // added by [Yor] - battle_config.packet_ver_flag = 511; // added by [Yor] + battle_config.packet_ver_flag = 255; // added by [Yor] battle_config.min_hair_style = 0; battle_config.max_hair_style = 20; battle_config.min_hair_color = 0; @@ -5434,13 +4444,18 @@ void battle_set_defaults() { battle_config.skill_steal_type = 1; battle_config.skill_steal_rate = 100; battle_config.night_darkness_level = 9; - + battle_config.motd_type = 0; + battle_config.allow_atcommand_when_mute = 0; + battle_config.finding_ore_rate = 100; battle_config.castrate_dex_scale = 150; - battle_config.area_size = 14; + battle_config.exp_calc_type = 1; + battle_config.min_skill_delay_limit = 100; + battle_config.require_glory_guild = 0; + battle_config.idle_no_share = 0; //SQL-only options start -#ifndef TXT_ONLY +#ifndef TXT_ONLY battle_config.mail_system = 0; //SQL-only options end #endif @@ -5477,6 +4492,10 @@ void battle_validate_conf() { battle_config.max_aspd = 10; if(battle_config.max_aspd > 1000) battle_config.max_aspd = 1000; + if(battle_config.hp_rate < 0) + battle_config.hp_rate = 1; + if(battle_config.sp_rate < 0) + battle_config.sp_rate = 1; if(battle_config.max_hp > 1000000) battle_config.max_hp = 1000000; if(battle_config.max_hp < 100) @@ -5495,10 +4514,10 @@ void battle_validate_conf() { battle_config.max_cart_weight = 100; battle_config.max_cart_weight *= 10; - if(battle_config.agi_penaly_count < 2) - battle_config.agi_penaly_count = 2; - if(battle_config.vit_penaly_count < 2) - battle_config.vit_penaly_count = 2; + if(battle_config.agi_penalty_count < 2) + battle_config.agi_penalty_count = 2; + if(battle_config.vit_penalty_count < 2) + battle_config.vit_penalty_count = 2; if(battle_config.guild_exp_limit > 99) battle_config.guild_exp_limit = 99; @@ -5530,11 +4549,11 @@ void battle_validate_conf() { battle_config.night_at_start = 0; else if (battle_config.night_at_start > 1) // added by [Yor] battle_config.night_at_start = 1; - if (battle_config.day_duration < 0) // added by [Yor] - battle_config.day_duration = 0; - if (battle_config.night_duration < 0) // added by [Yor] - battle_config.night_duration = 0; - + if (battle_config.day_duration != 0 && battle_config.day_duration < 60000) // added by [Yor] + battle_config.day_duration = 60000; + if (battle_config.night_duration != 0 && battle_config.night_duration < 60000) // added by [Yor] + battle_config.night_duration = 60000; + if (battle_config.ban_spoof_namer < 0) // added by [Yor] battle_config.ban_spoof_namer = 0; else if (battle_config.ban_spoof_namer > 32767) @@ -5551,33 +4570,43 @@ void battle_validate_conf() { battle_config.any_warp_GM_min_level = 100; // at least 1 client must be accepted - if ((battle_config.packet_ver_flag & 511) == 0) // added by [Yor] - battle_config.packet_ver_flag = 511; // accept all clients - + if ((battle_config.packet_ver_flag & 255) == 0) // added by [Yor] + battle_config.packet_ver_flag = 255; // accept all clients + if (battle_config.night_darkness_level > 10) // Celest battle_config.night_darkness_level = 10; + if (battle_config.motd_type < 0) + battle_config.motd_type = 0; + else if (battle_config.motd_type > 1) + battle_config.motd_type = 1; + + if (battle_config.finding_ore_rate < 0) + battle_config.finding_ore_rate = 0; + if (battle_config.vending_max_value > 10000000 || battle_config.vending_max_value<=0) // Lupus & Kobra_k88 battle_config.vending_max_value = 10000000; + if (battle_config.min_skill_delay_limit < 10) + battle_config.min_skill_delay_limit = 10; // minimum delay of 10ms } /*========================================== * Ý’èƒtƒ@ƒCƒ‹‚ð“ǂݞ‚Þ *------------------------------------------ */ -int battle_config_read(const char *cfgName) +int battle_config_read(const char *cfgName) { char line[1024], w1[1024], w2[1024]; FILE *fp; static int count = 0; - if ((count++) == 0) + if ((count++) == 0) battle_set_defaults(); fp = fopen(cfgName,"r"); if (fp == NULL) { - printf("file not found: %s\n", cfgName); + printf("File not found: %s\n", cfgName); return 1; } while(fgets(line,1020,fp)){ diff --git a/src/map/battle.h b/src/map/battle.h index f6f0345ca..393cc58b4 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -63,50 +63,6 @@ int battle_weapon_attack( struct block_list *bl,struct block_list *target, // ŠeŽíƒpƒ‰ƒ[ƒ^‚𓾂é int battle_counttargeted(struct block_list *bl,struct block_list *src,int target_lv); -int battle_get_class(struct block_list *bl); -int battle_get_dir(struct block_list *bl); -int battle_get_lv(struct block_list *bl); -int battle_get_range(struct block_list *bl); -int battle_get_hp(struct block_list *bl); -int battle_get_max_hp(struct block_list *bl); -int battle_get_str(struct block_list *bl); -int battle_get_agi(struct block_list *bl); -int battle_get_vit(struct block_list *bl); -int battle_get_int(struct block_list *bl); -int battle_get_dex(struct block_list *bl); -int battle_get_luk(struct block_list *bl); -int battle_get_hit(struct block_list *bl); -int battle_get_flee(struct block_list *bl); -int battle_get_def(struct block_list *bl); -int battle_get_mdef(struct block_list *bl); -int battle_get_flee2(struct block_list *bl); -int battle_get_def2(struct block_list *bl); -int battle_get_mdef2(struct block_list *bl); -int battle_get_baseatk(struct block_list *bl); -int battle_get_atk(struct block_list *bl); -int battle_get_atk2(struct block_list *bl); -int battle_get_speed(struct block_list *bl); -int battle_get_adelay(struct block_list *bl); -int battle_get_amotion(struct block_list *bl); -int battle_get_dmotion(struct block_list *bl); -int battle_get_element(struct block_list *bl); -int battle_get_attack_element(struct block_list *bl); -int battle_get_attack_element2(struct block_list *bl); //¶Žè•Ší‘®«Žæ“¾ -#define battle_get_elem_type(bl) (battle_get_element(bl)%10) -#define battle_get_elem_level(bl) (battle_get_element(bl)/10/2) -int battle_get_party_id(struct block_list *bl); -int battle_get_guild_id(struct block_list *bl); -int battle_get_race(struct block_list *bl); -int battle_get_size(struct block_list *bl); -int battle_get_mode(struct block_list *bl); -int battle_get_mexp(struct block_list *bl); - -struct status_change *battle_get_sc_data(struct block_list *bl); -short *battle_get_sc_count(struct block_list *bl); -short *battle_get_opt1(struct block_list *bl); -short *battle_get_opt2(struct block_list *bl); -short *battle_get_opt3(struct block_list *bl); -short *battle_get_option(struct block_list *bl); enum { BCT_NOENEMY =0x00000, @@ -115,6 +71,7 @@ enum { BCT_NOPARTY =0x50000, BCT_ALL =0x20000, BCT_NOONE =0x60000, + BCT_SELF =0x60000, }; int battle_check_undead(int race,int element); @@ -174,7 +131,6 @@ extern struct Battle_Config { int skillup_limit; int wp_rate; int pp_rate; - int cdp_rate; int monster_active_enable; int monster_damage_delay_rate; int monster_loot_type; @@ -212,12 +168,17 @@ extern struct Battle_Config { int natural_heal_skill_interval; int natural_heal_weight_rate; int item_name_override_grffile; + int indoors_override_grffile; // [Celest] + int skill_sp_override_grffile; // [Celest] + int cardillust_read_grffile; + int item_equip_override_grffile; + int item_slots_override_grffile; int arrow_decrement; int max_aspd; int max_hp; int max_sp; int max_lv; - int max_parameter; + unsigned int max_parameter; int max_cart_weight; int pc_skill_log; int mob_skill_log; @@ -229,12 +190,12 @@ extern struct Battle_Config { int undead_detect_type; int pc_auto_counter_type; int monster_auto_counter_type; - int agi_penaly_type; - int agi_penaly_count; - int agi_penaly_num; - int vit_penaly_type; - int vit_penaly_count; - int vit_penaly_num; + int agi_penalty_type; + int agi_penalty_count; + int agi_penalty_num; + int vit_penalty_type; + int vit_penalty_count; + int vit_penalty_num; int player_defense_type; int monster_defense_type; int pet_defense_type; @@ -253,10 +214,9 @@ extern struct Battle_Config { int mob_changetarget_byskill; int pc_attack_direction_change; int monster_attack_direction_change; - int pc_undead_nofreeze; int pc_land_skill_limit; int monster_land_skill_limit; - int party_skill_penaly; + int party_skill_penalty; int monster_class_change_full_recover; int produce_item_name_input; int produce_potion_name_input; @@ -271,7 +231,6 @@ extern struct Battle_Config { // int pet_lootitem; // removed [Valaris] // int pet_weight; // removed [Valaris] int show_steal_in_same_party; - int enable_upper_class; int pet_attack_attr_none; int mob_attack_attr_none; int mob_ghostring_fix; @@ -287,7 +246,7 @@ extern struct Battle_Config { int prevent_logout; // Added by RoVeRT int alchemist_summon_reward; // [Valaris] - int maximum_level; + unsigned int maximum_level; int drops_by_luk; int monsters_ignore_gm; int equipment_breaking; @@ -297,8 +256,8 @@ extern struct Battle_Config { int pk_mode; int show_mob_hp; // end additions [Valaris] - int agi_penaly_count_lv; - int vit_penaly_count_lv; + int agi_penalty_count_lv; + int vit_penalty_count_lv; int gx_allhit; int gx_cardfix; @@ -312,18 +271,25 @@ extern struct Battle_Config { int skill_removetrap_type; int disp_experience; int castle_defense_rate; - int riding_weight; int backstab_bow_penalty; + int hp_rate; + int sp_rate; + int gm_can_drop_lv; + int disp_hpmeter; + int bone_drop; + int monster_damage_delay; +// eAthena additions int night_at_start; // added by [Yor] int day_duration; // added by [Yor] int night_duration; // added by [Yor] int ban_spoof_namer; // added by [Yor] + int ban_hack_trade; // added by [Yor] int hack_info_GM_level; // added by [Yor] int any_warp_GM_min_level; // added by [Yor] int packet_ver_flag; // added by [Yor] - int muting_players; // added by [Apple] - + int muting_players; // added by [PoW] + int min_hair_style; // added by [MouseJstr] int max_hair_style; // added by [MouseJstr] int min_hair_color; // added by [MouseJstr] @@ -336,10 +302,17 @@ extern struct Battle_Config { int zeny_from_mobs; // [Valaris] int mobs_level_up; // [Valaris] - int pk_min_level; // [celest] + unsigned int pk_min_level; // [celest] int skill_steal_type; // [celest] int skill_steal_rate; // [celest] int night_darkness_level; // [celest] + int motd_type; // [celest] + int allow_atcommand_when_mute; // [celest] + int finding_ore_rate; // orn + int exp_calc_type; + int min_skill_delay_limit; + int require_glory_guild; + int idle_no_share; #ifndef TXT_ONLY /* SQL-only options */ int mail_system; // [Valaris] diff --git a/src/map/charcommand.c b/src/map/charcommand.c index de05e20ae..9b700dc47 100644 --- a/src/map/charcommand.c +++ b/src/map/charcommand.c @@ -15,6 +15,7 @@ #include "itemdb.h" #include "map.h" #include "pc.h" +#include "status.h" #include "skill.h" #include "mob.h" #include "pet.h" @@ -27,10 +28,11 @@ #include "npc.h" #include "trade.h" #include "core.h" +#include "showmsg.h" static char command_symbol = '#'; -static char msg_table[1000][1024]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others) +extern char *msg_table[1000]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others) #define CCMD_FUNC(x) int charcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message) @@ -42,6 +44,15 @@ CCMD_FUNC(option); CCMD_FUNC(save); CCMD_FUNC(stats_all); CCMD_FUNC(reset); +CCMD_FUNC(spiritball); +CCMD_FUNC(itemlist); +CCMD_FUNC(effect); +CCMD_FUNC(storagelist); +CCMD_FUNC(item); +CCMD_FUNC(warp); +CCMD_FUNC(zeny); +CCMD_FUNC(showexp); +CCMD_FUNC(showdelay); #ifdef TXT_ONLY /* TXT_ONLY */ @@ -70,6 +81,18 @@ static CharCommandInfo charcommand_info[] = { { CharCommandReset, "#reset", 60, charcommand_reset }, { CharCommandSave, "#save", 60, charcommand_save }, { CharCommandStatsAll, "#statsall", 40, charcommand_stats_all }, + { CharCommandSpiritball, "#spiritball", 40, charcommand_spiritball }, + { CharCommandItemList, "#itemlist", 40, charcommand_itemlist }, + { CharCommandEffect, "#effect", 40, charcommand_effect }, + { CharCommandStorageList, "#storagelist", 40, charcommand_storagelist }, + { CharCommandItem, "#item", 60, charcommand_item }, + { CharCommandWarp, "#warp", 60, charcommand_warp }, + { CharCommandWarp, "#rura", 60, charcommand_warp }, + { CharCommandWarp, "#rura+", 60, charcommand_warp }, + { CharCommandZeny, "#zeny", 60, charcommand_zeny }, + { CharCommandShowExp, "#showexp", 0, charcommand_showexp}, + { CharCommandShowDelay, "#showdelay", 0, charcommand_showdelay}, + #ifdef TXT_ONLY /* TXT_ONLY */ @@ -248,8 +271,8 @@ int charcommand_config_read(const char *cfgName) { charcommand_config_read(w2); else if (strcmpi(w1, "command_symbol") == 0 && w2[0] > 31 && w2[0] != '/' && // symbol of standard ragnarok GM commands - w2[0] != '%' && // symbol of party chat speaking - w2[0] != '@') // symbol for @commands + w2[0] != '%' // symbol of party chat speaking + ) command_symbol = w2[0]; } fclose(fp); @@ -285,23 +308,24 @@ int charcommand_jobchange( } if ((pl_sd = map_nick2sd(character)) != NULL) { + int j; if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can change job only to lower or same level if ((job >= 0 && job < MAX_PC_CLASS)) { // fix pecopeco display if ((job != 13 && job != 21 && job != 4014 && job != 4022)) { if (pc_isriding(sd)) { - if (pl_sd->status.class == 13) - pl_sd->status.class = pl_sd->view_class = 7; - if (pl_sd->status.class == 21) - pl_sd->status.class = pl_sd->view_class = 14; - if (pl_sd->status.class == 4014) - pl_sd->status.class = pl_sd->view_class = 4008; - if (pl_sd->status.class == 4022) - pl_sd->status.class = pl_sd->view_class = 4015; + if (pl_sd->status.class_ == 13) + pl_sd->status.class_ = pl_sd->view_class = 7; + if (pl_sd->status.class_ == 21) + pl_sd->status.class_ = pl_sd->view_class = 14; + if (pl_sd->status.class_ == 4014) + pl_sd->status.class_ = pl_sd->view_class = 4008; + if (pl_sd->status.class_ == 4022) + pl_sd->status.class_ = pl_sd->view_class = 4015; pl_sd->status.option &= ~0x0020; clif_changeoption(&pl_sd->bl); - pc_calcstatus(pl_sd, 0); + status_calc_pc(pl_sd, 0); } } else { if (!pc_isriding(sd)) { @@ -315,7 +339,10 @@ int charcommand_jobchange( job = 4015; } } - + for (j=0; j < MAX_INVENTORY; j++) { + if(pl_sd->status.inventory[j].nameid>0 && pl_sd->status.inventory[j].equip!=0) + pc_unequipitem(pl_sd, j, 3); + } if (pc_jobchange(pl_sd, job, upper) == 0) clif_displaymessage(fd, msg_table[48]); // Character's job changed. else { @@ -412,9 +439,9 @@ int charcommand_petfriendly( if ((pl_sd->pet.intimate > 0 && t <= 0) || (pl_sd->pet.intimate <= 0 && t > 0)) { if (pl_sd->bl.prev != NULL) - pc_calcstatus(pl_sd, 0); + status_calc_pc(pl_sd, 0); else - pc_calcstatus(pl_sd, 2); + status_calc_pc(pl_sd, 2); } } clif_displaymessage(pl_sd->fd, msg_table[182]); // Pet friendly value changed! @@ -481,7 +508,7 @@ int charcommand_stats( { "Zeny - %d", pl_sd->status.zeny }, { NULL, 0 } }; - sprintf(job_jobname, "Job - %s %s", job_name(pl_sd->status.class), "(level %d)"); + sprintf(job_jobname, "Job - %s %s", job_name(pl_sd->status.class_), "(level %d)"); sprintf(output, msg_table[53], pl_sd->status.name); // '%s' stats: clif_displaymessage(fd, output); for (i = 0; output_table[i].format != NULL; i++) { @@ -561,37 +588,37 @@ int charcommand_option( pl_sd->opt2 = opt2; pl_sd->status.option = opt3; // fix pecopeco display - if (pl_sd->status.class == 13 || pl_sd->status.class == 21 || pl_sd->status.class == 4014 || pl_sd->status.class == 4022) { + if (pl_sd->status.class_ == 13 || pl_sd->status.class_ == 21 || pl_sd->status.class_ == 4014 || pl_sd->status.class_ == 4022) { if (!pc_isriding(pl_sd)) { // pl_sd have the new value... - if (pl_sd->status.class == 13) - pl_sd->status.class = pl_sd->view_class = 7; - else if (pl_sd->status.class == 21) - pl_sd->status.class = pl_sd->view_class = 14; - else if (pl_sd->status.class == 4014) - pl_sd->status.class = pl_sd->view_class = 4008; - else if (pl_sd->status.class == 4022) - pl_sd->status.class = pl_sd->view_class = 4015; + if (pl_sd->status.class_ == 13) + pl_sd->status.class_ = pl_sd->view_class = 7; + else if (pl_sd->status.class_ == 21) + pl_sd->status.class_ = pl_sd->view_class = 14; + else if (pl_sd->status.class_ == 4014) + pl_sd->status.class_ = pl_sd->view_class = 4008; + else if (pl_sd->status.class_ == 4022) + pl_sd->status.class_ = pl_sd->view_class = 4015; } } else { if (pc_isriding(pl_sd)) { // pl_sd have the new value... if (pl_sd->disguise > 0) { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris] (code added by [Yor]) pl_sd->status.option &= ~0x0020; } else { - if (pl_sd->status.class == 7) - pl_sd->status.class = pl_sd->view_class = 13; - else if (pl_sd->status.class == 14) - pl_sd->status.class = pl_sd->view_class = 21; - else if (pl_sd->status.class == 4008) - pl_sd->status.class = pl_sd->view_class = 4014; - else if (pl_sd->status.class == 4015) - pl_sd->status.class = pl_sd->view_class = 4022; + if (pl_sd->status.class_ == 7) + pl_sd->status.class_ = pl_sd->view_class = 13; + else if (pl_sd->status.class_ == 14) + pl_sd->status.class_ = pl_sd->view_class = 21; + else if (pl_sd->status.class_ == 4008) + pl_sd->status.class_ = pl_sd->view_class = 4014; + else if (pl_sd->status.class_ == 4015) + pl_sd->status.class_ = pl_sd->view_class = 4022; else pl_sd->status.option &= ~0x0020; } } } clif_changeoption(&pl_sd->bl); - pc_calcstatus(pl_sd, 0); + status_calc_pc(pl_sd, 0); clif_displaymessage(fd, msg_table[58]); // Character's options changed. } else { clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. @@ -673,14 +700,14 @@ int charcommand_stats_all(const int fd, struct map_session_data* sd, const char* count = 0; for(i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { if (pc_isGM(pl_sd) > 0) sprintf(gmlevel, "| GM Lvl: %d", pc_isGM(pl_sd)); else sprintf(gmlevel, " "); - sprintf(output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d) | HP: %d/%d | SP: %d/%d", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class), pl_sd->status.job_level, pl_sd->status.hp, pl_sd->status.max_hp, pl_sd->status.sp, pl_sd->status.max_sp); + sprintf(output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d) | HP: %d/%d | SP: %d/%d", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level, pl_sd->status.hp, pl_sd->status.max_hp, pl_sd->status.sp, pl_sd->status.max_sp); clif_displaymessage(fd, output); sprintf(output, "STR: %d | AGI: %d | VIT: %d | INT: %d | DEX: %d | LUK: %d | Zeny: %d %s", pl_sd->status.str, pl_sd->status.agi, pl_sd->status.vit, pl_sd->status.int_, pl_sd->status.dex, pl_sd->status.luk, pl_sd->status.zeny, gmlevel); clif_displaymessage(fd, output); @@ -701,3 +728,530 @@ int charcommand_stats_all(const int fd, struct map_session_data* sd, const char* return 0; } +/*========================================== + * CharSpiritBall Function by PalasX + *------------------------------------------ + */ +int charcommand_spiritball(const int fd, struct map_session_data* sd,const char* command, const char* message) +{ + struct map_session_data *pl_sd; + char character[100]; + int spirit = 0; + + memset(character, '\0', sizeof(character)); + + if(!message || !*message || sscanf(message, "%d %99[^\n]", &spirit, character) < 2 || spirit < 0 || spirit > 1000) { + clif_displaymessage(fd, "Usage: @spiritball <number: 0-1000>) <CHARACTER_NAME>."); + return -1; + } + + if((pl_sd = map_nick2sd(character)) != NULL) { + if (spirit >= 0 && spirit <= 0x7FFF) { + if (pl_sd->spiritball != spirit || spirit > 999) { + if (pl_sd->spiritball > 0) + pc_delspiritball(pl_sd, pl_sd->spiritball, 1); + pl_sd->spiritball = spirit; + clif_spiritball(pl_sd); + // no message, player can look the difference + if (spirit > 1000) + clif_displaymessage(fd, msg_table[204]); // WARNING: more than 1000 spiritballs can CRASH your server and/or client! + } else { + clif_displaymessage(fd, msg_table[205]); // You already have this number of spiritballs. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[37]); // An invalid number was specified. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[3]); // Character not found. + return -1; + } + return 0; +} + +/*========================================== + * #itemlist <character>: Displays the list of a player's items. + *------------------------------------------ + */ +int +charcommand_itemlist( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct map_session_data *pl_sd; + struct item_data *item_data, *item_temp; + int i, j, equip, count, counter, counter2; + char character[100], output[200], equipstr[100], outputtmp[200]; + nullpo_retr(-1, sd); + + memset(character, '\0', sizeof(character)); + memset(output, '\0', sizeof(output)); + memset(equipstr, '\0', sizeof(equipstr)); + memset(outputtmp, '\0', sizeof(outputtmp)); + + if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + clif_displaymessage(fd, "Please, enter a player name (usage: #itemlist <char name>)."); + return -1; + } + + if ((pl_sd = map_nick2sd(character)) != NULL) { + if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can look items only lower or same level + counter = 0; + count = 0; + for (i = 0; i < MAX_INVENTORY; i++) { + if (pl_sd->status.inventory[i].nameid > 0 && (item_data = itemdb_search(pl_sd->status.inventory[i].nameid)) != NULL) { + counter = counter + pl_sd->status.inventory[i].amount; + count++; + if (count == 1) { + sprintf(output, "------ Items list of '%s' ------", pl_sd->status.name); + clif_displaymessage(fd, output); + } + if ((equip = pl_sd->status.inventory[i].equip)) { + strcpy(equipstr, "| equiped: "); + if (equip & 4) + strcat(equipstr, "robe/gargment, "); + if (equip & 8) + strcat(equipstr, "left accessory, "); + if (equip & 16) + strcat(equipstr, "body/armor, "); + if ((equip & 34) == 2) + strcat(equipstr, "right hand, "); + if ((equip & 34) == 32) + strcat(equipstr, "left hand, "); + if ((equip & 34) == 34) + strcat(equipstr, "both hands, "); + if (equip & 64) + strcat(equipstr, "feet, "); + if (equip & 128) + strcat(equipstr, "right accessory, "); + if ((equip & 769) == 1) + strcat(equipstr, "lower head, "); + if ((equip & 769) == 256) + strcat(equipstr, "top head, "); + if ((equip & 769) == 257) + strcat(equipstr, "lower/top head, "); + if ((equip & 769) == 512) + strcat(equipstr, "mid head, "); + if ((equip & 769) == 512) + strcat(equipstr, "lower/mid head, "); + if ((equip & 769) == 769) + strcat(equipstr, "lower/mid/top head, "); + // remove final ', ' + equipstr[strlen(equipstr) - 2] = '\0'; + } else + memset(equipstr, '\0', sizeof(equipstr)); + if (sd->status.inventory[i].refine) + sprintf(output, "%d %s %+d (%s %+d, id: %d) %s", pl_sd->status.inventory[i].amount, item_data->name, pl_sd->status.inventory[i].refine, item_data->jname, pl_sd->status.inventory[i].refine, pl_sd->status.inventory[i].nameid, equipstr); + else + sprintf(output, "%d %s (%s, id: %d) %s", pl_sd->status.inventory[i].amount, item_data->name, item_data->jname, pl_sd->status.inventory[i].nameid, equipstr); + clif_displaymessage(fd, output); + memset(output, '\0', sizeof(output)); + counter2 = 0; + for (j = 0; j < item_data->slot; j++) { + if (pl_sd->status.inventory[i].card[j]) { + if ((item_temp = itemdb_search(pl_sd->status.inventory[i].card[j])) != NULL) { + if (output[0] == '\0') + sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname); + else + sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname); + strcat(output, outputtmp); + } + } + } + if (output[0] != '\0') { + output[strlen(output) - 2] = ')'; + output[strlen(output) - 1] = '\0'; + clif_displaymessage(fd, output); + } + } + } + if (count == 0) + clif_displaymessage(fd, "No item found on this player."); + else { + sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count); + clif_displaymessage(fd, output); + } + } else { + clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[3]); // Character not found. + return -1; + } + + return 0; +} + +/*========================================== + * #effect by [MouseJstr] + * + * Create a effect localized on another character + *------------------------------------------ + */ +int +charcommand_effect(const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct map_session_data *pl_sd = NULL; + char target[255]; + int type = 0; + nullpo_retr(-1, sd); + + if (!message || !*message || sscanf(message, "%d %s", &type, target) != 2) { + clif_displaymessage(fd, "usage: #effect <type+> <target>."); + return -1; + } + + if((pl_sd=map_nick2sd((char *) target)) == NULL) + return -1; + + clif_specialeffect(&pl_sd->bl, type, 0); + clif_displaymessage(fd, msg_table[229]); // Your effect has changed. + + return 0; +} + +/*========================================== + * #storagelist <character>: Displays the items list of a player's storage. + *------------------------------------------ + */ +int +charcommand_storagelist( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct storage *stor; + struct map_session_data *pl_sd; + struct item_data *item_data, *item_temp; + int i, j, count, counter, counter2; + char character[100], output[200], outputtmp[200]; + nullpo_retr(-1, sd); + + memset(character, '\0', sizeof(character)); + memset(output, '\0', sizeof(output)); + memset(outputtmp, '\0', sizeof(outputtmp)); + + if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + clif_displaymessage(fd, "Please, enter a player name (usage: #itemlist <char name>)."); + return -1; + } + + if ((pl_sd = map_nick2sd(character)) != NULL) { + if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can look items only lower or same level + if((stor = account2storage2(pl_sd->status.account_id)) != NULL) { + counter = 0; + count = 0; + for (i = 0; i < MAX_STORAGE; i++) { + if (stor->storage_[i].nameid > 0 && (item_data = itemdb_search(stor->storage_[i].nameid)) != NULL) { + counter = counter + stor->storage_[i].amount; + count++; + if (count == 1) { + sprintf(output, "------ Storage items list of '%s' ------", pl_sd->status.name); + clif_displaymessage(fd, output); + } + if (stor->storage_[i].refine) + sprintf(output, "%d %s %+d (%s %+d, id: %d)", stor->storage_[i].amount, item_data->name, stor->storage_[i].refine, item_data->jname, stor->storage_[i].refine, stor->storage_[i].nameid); + else + sprintf(output, "%d %s (%s, id: %d)", stor->storage_[i].amount, item_data->name, item_data->jname, stor->storage_[i].nameid); + clif_displaymessage(fd, output); + memset(output, '\0', sizeof(output)); + counter2 = 0; + for (j = 0; j < item_data->slot; j++) { + if (stor->storage_[i].card[j]) { + if ((item_temp = itemdb_search(stor->storage_[i].card[j])) != NULL) { + if (output[0] == '\0') + sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname); + else + sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname); + strcat(output, outputtmp); + } + } + } + if (output[0] != '\0') { + output[strlen(output) - 2] = ')'; + output[strlen(output) - 1] = '\0'; + clif_displaymessage(fd, output); + } + } + } + if (count == 0) + clif_displaymessage(fd, "No item found in the storage of this player."); + else { + sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count); + clif_displaymessage(fd, output); + } + } else { + clif_displaymessage(fd, "This player has no storage."); + return 0; + } + } else { + clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[3]); // Character not found. + return -1; + } + + return 0; +} + +static void +charcommand_giveitem_sub(struct map_session_data *sd,struct item_data *item_data,int number) +{ + int flag = 0; + int loop = 1, get_count = number,i; + struct item item_tmp; + + if(sd && item_data){ + if (item_data->type == 4 || item_data->type == 5 || + item_data->type == 7 || item_data->type == 8) { + loop = number; + get_count = 1; + } + for (i = 0; i < loop; i++) { + memset(&item_tmp, 0, sizeof(item_tmp)); + item_tmp.nameid = item_data->nameid; + item_tmp.identify = 1; + if ((flag = pc_additem((struct map_session_data*)sd, + &item_tmp, get_count))) + clif_additem((struct map_session_data*)sd, 0, 0, flag); + } + } +} +/*========================================== + * #item command (usage: #item <name/id_of_item> <quantity> <player>) + * by MC Cameri + *------------------------------------------ + */ +int charcommand_item( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char item_name[100]; + char character[100]; + struct map_session_data *pl_sd; + int number = 0, item_id, flag; + struct item item_tmp; + struct item_data *item_data; + int get_count, i, pet_id; + nullpo_retr(-1, sd); + + memset(item_name, '\0', sizeof(item_name)); + + if (!message || !*message || sscanf(message, "%99s %d %99[^\n]", item_name, &number, character) < 3) { + clif_displaymessage(fd, "Please, enter an item name/id (usage: #item <item name or ID> <quantity> <char name>)."); + return -1; + } + + if (number <= 0) + number = 1; + + item_id = 0; + if ((item_data = itemdb_searchname(item_name)) != NULL || + (item_data = itemdb_exists(atoi(item_name))) != NULL) + item_id = item_data->nameid; + + if (item_id >= 500) { + get_count = number; + // check pet egg + pet_id = search_petDB_index(item_id, PET_EGG); + if (item_data->type == 4 || item_data->type == 5 || + item_data->type == 7 || item_data->type == 8) { + get_count = 1; + } + if ((pl_sd = map_nick2sd(character)) != NULL) { + if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can look items only lower or same level + for (i = 0; i < number; i += get_count) { + // if pet egg + if (pet_id >= 0) { + pl_sd->catch_target_class = pet_db[pet_id].class_; + intif_create_pet(pl_sd->status.account_id, pl_sd->status.char_id, + (short)pet_db[pet_id].class_, (short)mob_db[pet_db[pet_id].class_].lv, + (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate, + 100, 0, 1, pet_db[pet_id].jname); + // if not pet egg + } else { + memset(&item_tmp, 0, sizeof(item_tmp)); + item_tmp.nameid = item_id; + item_tmp.identify = 1; + if ((flag = pc_additem(pl_sd, &item_tmp, get_count))) + clif_additem(pl_sd, 0, 0, flag); + } + } + clif_displaymessage(fd, msg_table[18]); // Item created. + } else { + clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. + return -1; + } + } else if(/* from jA's @giveitem */strcmpi(character,"all")==0 || strcmpi(character,"everyone")==0){ + for (i = 0; i < fd_max; i++) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data)){ + charcommand_giveitem_sub(pl_sd,item_data,number); + snprintf(tmp_output, sizeof(tmp_output), "You got %s %d.", item_name,number); + clif_displaymessage(pl_sd->fd, tmp_output); + } + } + snprintf(tmp_output, sizeof(tmp_output), "%s received %s %d.","Everyone",item_name,number); + clif_displaymessage(fd, tmp_output); + } else { + clif_displaymessage(fd, msg_table[3]); // Character not found. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[19]); // Invalid item ID or name. + return -1; + } + + return 0; +} + +/*========================================== + * #warp/#rura/#rura+ <mapname> <x> <y> <char name> + *------------------------------------------ + */ +int charcommand_warp( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char map_name[100]; + char character[100]; + int x = 0, y = 0; + struct map_session_data *pl_sd; + int m; + + nullpo_retr(-1, sd); + + memset(map_name, '\0', sizeof(map_name)); + memset(character, '\0', sizeof(character)); + + if (!message || !*message || sscanf(message, "%99s %d %d %99[^\n]", map_name, &x, &y, character) < 4) { + clif_displaymessage(fd, "Usage: #warp/#rura/#rura+ <mapname> <x> <y> <char name>"); + return -1; + } + + if (x <= 0) + x = rand() % 399 + 1; + if (y <= 0) + y = rand() % 399 + 1; + if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat) + strcat(map_name, ".gat"); + + if ((pl_sd = map_nick2sd(character)) != NULL) { + if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can rura+ only lower or same GM level + if (x > 0 && x < 400 && y > 0 && y < 400) { + m = map_mapname2mapid(map_name); + if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + clif_displaymessage(fd, "You are not authorised to warp someone to this map."); + return -1; + } + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + clif_displaymessage(fd, "You are not authorised to warp this player from its actual map."); + return -1; + } + if (pc_setpos(pl_sd, map_name, x, y, 3) == 0) { + clif_displaymessage(pl_sd->fd, msg_table[0]); // Warped. + clif_displaymessage(fd, msg_table[15]); // Player warped (message sends to player too). + } else { + clif_displaymessage(fd, msg_table[1]); // Map not found. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[2]); // Coordinates out of range. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[3]); // Character not found. + return -1; + } + + return 0; +} + +/*========================================== + * #zeny <charname> + *------------------------------------------ + */ +int charcommand_zeny( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + struct map_session_data *pl_sd; + char character[100]; + int zeny = 0, new_zeny; + nullpo_retr(-1, sd); + + memset(character, '\0', sizeof(character)); + + if (!message || !*message || sscanf(message, "%d %99[^\n]", &zeny, character) < 2 || zeny == 0) { + clif_displaymessage(fd, "Please, enter a number and a player name (usage: #zeny <zeny> <name>)."); + return -1; + } + + if ((pl_sd = map_nick2sd(character)) != NULL) { + new_zeny = pl_sd->status.zeny + zeny; + if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY)) // fix positiv overflow + new_zeny = MAX_ZENY; + else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0)) // fix negativ overflow + new_zeny = 0; + if (new_zeny != pl_sd->status.zeny) { + pl_sd->status.zeny = new_zeny; + clif_updatestatus(pl_sd, SP_ZENY); + clif_displaymessage(fd, msg_table[211]); // Character's number of zenys changed! + } else { + if (zeny < 0) + clif_displaymessage(fd, msg_table[41]); // Impossible to decrease the number/value. + else + clif_displaymessage(fd, msg_table[149]); // Impossible to increase the number/value. + return -1; + } + } else { + clif_displaymessage(fd, msg_table[3]); // Character not found. + return -1; + } + + return 0; +} + +/*=================================== + * Remove some messages + *----------------------------------- + */ +int charcommand_showexp( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + if (sd->noexp) { + sd->noexp = 0; + clif_displaymessage(fd, "Gained exp is now shown"); + return 0; + } + else { + sd->noexp = 1; + clif_displaymessage(fd, "Gained exp is now NOT shown"); + return 0; + } +} + +int charcommand_showdelay( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + if (sd->nodelay) { + sd->nodelay = 0; + clif_displaymessage(fd, "Skill delay failure is now shown"); + return 0; + } + else { + sd->nodelay = 1; + clif_displaymessage(fd, "Skill delay failure is NOT now shown"); + return 0; + } +} + diff --git a/src/map/charcommand.h b/src/map/charcommand.h index 11babb816..7c1618cca 100644 --- a/src/map/charcommand.h +++ b/src/map/charcommand.h @@ -11,6 +11,15 @@ enum CharCommandType { CharCommandOption, CharCommandSave, CharCommandStatsAll, + CharCommandSpiritball, + CharCommandItemList, + CharCommandEffect, + CharCommandStorageList, + CharCommandItem, // by MC Cameri + CharCommandWarp, + CharCommandZeny, + CharCommandShowDelay, + CharCommandShowExp, #ifdef TXT_ONLY /* TXT_ONLY */ diff --git a/src/map/chat.c b/src/map/chat.c index 75788f03b..3bd29fec3 100644 --- a/src/map/chat.c +++ b/src/map/chat.c @@ -29,7 +29,7 @@ int chat_createchat(struct map_session_data *sd,int limit,int pub,char* pass,cha nullpo_retr(0, sd); - cd = aCalloc(1,sizeof(struct chat_data)); + cd = (struct chat_data *) aCalloc(1,sizeof(struct chat_data)); cd->limit = limit; cd->pub = pub; @@ -49,7 +49,7 @@ int chat_createchat(struct map_session_data *sd,int limit,int pub,char* pass,cha cd->bl.id = map_addobject(&cd->bl); if(cd->bl.id==0){ clif_createchat(sd,1); - free(cd); + aFree(cd); return 0; } pc_setchatid(sd,cd->bl.id); @@ -78,11 +78,11 @@ int chat_joinchat(struct map_session_data *sd,int chatid,char* pass) clif_joinchatfail(sd,0); return 0; } - if(cd->pub==0 && strncmp(pass,cd->pass,8)){ + if(cd->pub==0 && strncmp(pass,(char *) cd->pass,8)){ clif_joinchatfail(sd,1); return 0; } - if(chatid == sd->chatID) //Double Chat fix by Alex14, thx CHaNGeTe + if(chatid == (int)sd->chatID) //Double Chat fix by Alex14, thx CHaNGeTe { clif_joinchatfail(sd,1); return 0; @@ -268,14 +268,14 @@ int chat_createnpcchat(struct npc_data *nd,int limit,int pub,int trigger,char* t nullpo_retr(1, nd); - cd = aCalloc(1,sizeof(struct chat_data)); + cd = (struct chat_data *) aCalloc(1,sizeof(struct chat_data)); cd->limit = cd->trigger = limit; if(trigger>0) cd->trigger = trigger; cd->pub = pub; cd->users = 0; - memcpy(cd->pass,"",8); + memcpy(cd->pass,"",1); if(titlelen>=sizeof(cd->title)-1) titlelen=sizeof(cd->title)-1; memcpy(cd->title,title,titlelen); cd->title[titlelen]=0; @@ -286,11 +286,11 @@ int chat_createnpcchat(struct npc_data *nd,int limit,int pub,int trigger,char* t cd->bl.type = BL_CHAT; cd->owner_ = (struct block_list *)nd; cd->owner = &cd->owner_; - memcpy(cd->npc_event,ev,sizeof(cd->npc_event)); + memcpy(cd->npc_event,ev,strlen(ev)); cd->bl.id = map_addobject(&cd->bl); if(cd->bl.id==0){ - free(cd); + aFree(cd); return 0; } nd->chat_id=cd->bl.id; diff --git a/src/map/chrif.c b/src/map/chrif.c index adb26868d..e250c8a18 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -23,6 +23,7 @@ #include "npc.h" #include "pc.h" #include "nullpo.h" +#include "showmsg.h" #ifdef MEMWATCH #include "memwatch.h" @@ -35,20 +36,22 @@ static const int packet_len_table[0x20] = { -1,-1,10, 6,11,-1, 0, 0, // 2b10-2b17 }; -int char_fd; +int chrif_connected; +int char_fd = -1; int srvinfo; static char char_ip_str[16]; static int char_ip; static int char_port = 6121; static char userid[24], passwd[24]; -static int chrif_state; +static int chrif_state = 0; +static int char_init_done = 0; // Ý’èƒtƒ@ƒCƒ‹“ǂݞ‚ÝŠÖŒW /*========================================== * *------------------------------------------ */ -void chrif_setuserid(char *id) +void chrif_setuserid(char *id) { strncpy(userid, id, 24); } @@ -57,7 +60,7 @@ void chrif_setuserid(char *id) * *------------------------------------------ */ -void chrif_setpasswd(char *pwd) +void chrif_setpasswd(char *pwd) { strncpy(passwd, pwd, 24); } @@ -66,7 +69,7 @@ void chrif_setpasswd(char *pwd) * *------------------------------------------ */ -void chrif_setip(char *ip) +void chrif_setip(char *ip) { strncpy(char_ip_str, ip, 16); char_ip = inet_addr(char_ip_str); @@ -76,7 +79,7 @@ void chrif_setip(char *ip) * *------------------------------------------ */ -void chrif_setport(int port) +void chrif_setport(int port) { char_port = port; } @@ -85,7 +88,7 @@ void chrif_setport(int port) * *------------------------------------------ */ -int chrif_isconnect(void) +int chrif_isconnect(void) { return chrif_state == 2; } @@ -94,11 +97,11 @@ int chrif_isconnect(void) * *------------------------------------------ */ -int chrif_save(struct map_session_data *sd) +int chrif_save(struct map_session_data *sd) { nullpo_retr(-1, sd); - if (char_fd < 0) + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) return -1; pc_makesavestatus(sd); @@ -110,6 +113,8 @@ int chrif_save(struct map_session_data *sd) memcpy(WFIFOP(char_fd,12), &sd->status, sizeof(sd->status)); WFIFOSET(char_fd, WFIFOW(char_fd,2)); + storage_storage_save(sd); // to synchronise storage with character [Yor] + return 0; } @@ -117,7 +122,7 @@ int chrif_save(struct map_session_data *sd) * *------------------------------------------ */ -int chrif_connect(int fd) +int chrif_connect(int fd) { WFIFOW(fd,0) = 0x2af8; memcpy(WFIFOP(fd,2), userid, 24); @@ -134,13 +139,13 @@ int chrif_connect(int fd) * ƒ}ƒbƒv‘—M *------------------------------------------ */ -int chrif_sendmap(int fd) +int chrif_sendmap(int fd) { int i; WFIFOW(fd,0) = 0x2afa; for(i = 0; i < map_num; i++) - if (map[i].alias[0] != '\0') // [MouseJstr] map aliasing + if (map[i].alias != '\0') // [MouseJstr] map aliasing memcpy(WFIFOP(fd,4+i*16), map[i].alias, 16); else memcpy(WFIFOP(fd,4+i*16), map[i].name, 16); @@ -165,7 +170,7 @@ int chrif_recvmap(int fd) ip = RFIFOL(fd,4); port = RFIFOW(fd,8); for(i = 10, j = 0; i < RFIFOW(fd,2); i += 16, j++) { - map_setipport(RFIFOP(fd,i), ip, port); + map_setipport((char*)RFIFOP(fd,i), ip, port); // if (battle_config.etc_log) // printf("recv map %d %s\n", j, RFIFOP(fd,i)); } @@ -179,12 +184,15 @@ int chrif_recvmap(int fd) * ƒ}ƒbƒvŽIŠÔˆÚ“®‚Ì‚½‚߂̃f[ƒ^€”õ—v‹ *------------------------------------------ */ -int chrif_changemapserver(struct map_session_data *sd, char *name, int x, int y, int ip, short port) +int chrif_changemapserver(struct map_session_data *sd, char *name, int x, int y, int ip, short port) { int i, s_ip; nullpo_retr(-1, sd); + if( !sd || char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) + return -1; + s_ip = 0; for(i = 0; i < fd_max; i++) if (session[i] && session[i]->session_data == sd) { @@ -213,7 +221,7 @@ int chrif_changemapserver(struct map_session_data *sd, char *name, int x, int y, * ƒ}ƒbƒvŽIŠÔˆÚ“®ack *------------------------------------------ */ -int chrif_changemapserverack(int fd) +int chrif_changemapserverack(int fd) { struct map_session_data *sd = map_id2sd(RFIFOL(fd,2)); @@ -226,7 +234,7 @@ int chrif_changemapserverack(int fd) pc_authfail(sd->fd); return 0; } - clif_changemapserver(sd, RFIFOP(fd,18), RFIFOW(fd,34), RFIFOW(fd,36), RFIFOL(fd,38), RFIFOW(fd,42)); + clif_changemapserver(sd, (char*)RFIFOP(fd,18), RFIFOW(fd,34), RFIFOW(fd,36), RFIFOL(fd,38), RFIFOW(fd,42)); return 0; } @@ -235,19 +243,28 @@ int chrif_changemapserverack(int fd) * *------------------------------------------ */ -int chrif_connectack(int fd) +int chrif_connectack(int fd) { if (RFIFOB(fd,2)) { printf("Connected to char-server failed %d.\n", RFIFOB(fd,2)); exit(1); } - printf("Connected to char-server (connection #%d).\n", fd); + sprintf(tmp_output,"Successfully connected to Char Server (Connection: '"CL_WHITE"%d"CL_RESET"').\n",fd); + ShowStatus(tmp_output); chrif_state = 1; + chrif_connected=1; chrif_sendmap(fd); - printf("chrif: OnCharIfInit event done. (%d events)\n", npc_event_doall("OnCharIfInit")); - printf("chrif: OnInterIfInit event done. (%d events)\n", npc_event_doall("OnInterIfInit")); + sprintf(tmp_output,"Event '"CL_WHITE"OnCharIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnCharIfInit")); + ShowStatus(tmp_output); + sprintf(tmp_output,"Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit")); + ShowStatus(tmp_output); + if(!char_init_done) { + char_init_done = 1; + sprintf(tmp_output,"Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce")); + ShowStatus(tmp_output); + } // <Agit> Run Event [AgitInit] // printf("NPC_Event:[OnAgitInit] do (%d) events (Agit Initialize).\n", npc_event_doall("OnAgitInit")); @@ -259,7 +276,7 @@ int chrif_connectack(int fd) * *------------------------------------------ */ -int chrif_sendmapack(int fd) +int chrif_sendmapack(int fd) { if (RFIFOB(fd,2)) { printf("chrif : send map list to char server failed %d\n", RFIFOB(fd,2)); @@ -277,13 +294,15 @@ int chrif_sendmapack(int fd) * *------------------------------------------ */ -int chrif_authreq(struct map_session_data *sd) +int chrif_authreq(struct map_session_data *sd) { int i; nullpo_retr(-1, sd); - if (!sd || !char_fd || !sd->bl.id || !sd->login_id1) + if(!sd || !sd->bl.id || !sd->login_id1) + return -1; + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) return -1; for(i = 0; i < fd_max; i++) @@ -305,13 +324,15 @@ int chrif_authreq(struct map_session_data *sd) * *------------------------------------------ */ -int chrif_charselectreq(struct map_session_data *sd) +int chrif_charselectreq(struct map_session_data *sd) { int i, s_ip; nullpo_retr(-1, sd); - if(!sd || !char_fd || !sd->bl.id || !sd->login_id1) + if( !sd || !sd->bl.id || !sd->login_id1 ) + return -1; + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) return -1; s_ip = 0; @@ -335,9 +356,11 @@ int chrif_charselectreq(struct map_session_data *sd) * ƒLƒƒƒ‰–¼–â‚¢‡‚킹 *------------------------------------------ */ -int chrif_searchcharid(int char_id) +int chrif_searchcharid(int char_id) { - if (!char_id) + if( !char_id ) + return -1; + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) return -1; WFIFOW(char_fd,0) = 0x2b08; @@ -351,11 +374,14 @@ int chrif_searchcharid(int char_id) * GM‚ɕω»—v‹ *------------------------------------------ */ -int chrif_changegm(int id, const char *pass, int len) +int chrif_changegm(int id, const char *pass, int len) { if (battle_config.etc_log) printf("chrif_changegm: account: %d, password: '%s'.\n", id, pass); + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) + return -1; + WFIFOW(char_fd,0) = 0x2b0a; WFIFOW(char_fd,2) = len + 8; WFIFOL(char_fd,4) = id; @@ -369,11 +395,14 @@ int chrif_changegm(int id, const char *pass, int len) * Change Email *------------------------------------------ */ -int chrif_changeemail(int id, const char *actual_email, const char *new_email) +int chrif_changeemail(int id, const char *actual_email, const char *new_email) { if (battle_config.etc_log) printf("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n", id, actual_email, new_email); + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) + return -1; + WFIFOW(char_fd,0) = 0x2b0c; WFIFOL(char_fd,2) = id; memcpy(WFIFOP(char_fd,6), actual_email, 40); @@ -394,8 +423,11 @@ int chrif_changeemail(int id, const char *actual_email, const char *new_email) * 5: changesex *------------------------------------------ */ -int chrif_char_ask_name(int id, char * character_name, short operation_type, int year, int month, int day, int hour, int minute, int second) +int chrif_char_ask_name(int id, char * character_name, short operation_type, int year, int month, int day, int hour, int minute, int second) { + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) + return -1; + WFIFOW(char_fd, 0) = 0x2b0e; WFIFOL(char_fd, 2) = id; // account_id of who ask (for answer) -1 if nobody memcpy(WFIFOP(char_fd,6), character_name, 24); @@ -419,7 +451,10 @@ int chrif_char_ask_name(int id, char * character_name, short operation_type, int *------------------------------------------ */ int chrif_changesex(int id, int sex) { - WFIFOW(char_fd,0) = 0x3000; + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) + return -1; + + WFIFOW(char_fd,0) = 0x2b11; WFIFOW(char_fd,2) = 9; WFIFOL(char_fd,4) = id; WFIFOB(char_fd,8) = sex; @@ -444,7 +479,7 @@ int chrif_changesex(int id, int sex) { * 3: login-server offline *------------------------------------------ */ -int chrif_char_ask_name_answer(int fd) +int chrif_char_ask_name_answer(int fd) { int acc; struct map_session_data *sd; @@ -547,7 +582,7 @@ int chrif_char_ask_name_answer(int fd) * End of GM change (@GM) (modified by Yor) *------------------------------------------ */ -int chrif_changedgm(int fd) +int chrif_changedgm(int fd) { int acc, level; struct map_session_data *sd = NULL; @@ -573,7 +608,7 @@ int chrif_changedgm(int fd) * «•ʕω»I—¹ (modified by Yor) *------------------------------------------ */ -int chrif_changedsex(int fd) +int chrif_changedsex(int fd) { int acc, sex, i; struct map_session_data *sd; @@ -586,7 +621,7 @@ int chrif_changedsex(int fd) sd = map_id2sd(acc); if (acc > 0) { if (sd != NULL && sd->status.sex != sex) { - s_class = pc_calc_base_job(sd->status.class); + s_class = pc_calc_base_job(sd->status.class_); if (sd->status.sex == 0) { sd->status.sex = 1; sd->sex = 1; @@ -597,7 +632,7 @@ int chrif_changedsex(int fd) // to avoid any problem with equipment and invalid sex, equipment is unequiped. for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].nameid && sd->status.inventory[i].equip) - pc_unequipitem((struct map_session_data*)sd, i, 0, BF_NORMAL); + pc_unequipitem((struct map_session_data*)sd, i, 2); } // reset skill of some job if (s_class.job == 19 || s_class.job == 4020 || s_class.job == 4042 || @@ -621,15 +656,15 @@ int chrif_changedsex(int fd) clif_updatestatus(sd, SP_SKILLPOINT); // change job if necessary if (s_class.job == 20 || s_class.job == 4021 || s_class.job == 4043) - sd->status.class -= 1; + sd->status.class_ -= 1; else if (s_class.job == 19 || s_class.job == 4020 || s_class.job == 4042) - sd->status.class += 1; + sd->status.class_ += 1; } // save character chrif_save(sd); sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters // do same modify in login-server for the account, but no in char-server (it ask again login_id1 to login, and don't remember it) - clif_displaymessage(sd->fd, "Your sex has been changed (need disconexion by the server)..."); + clif_displaymessage(sd->fd, "Your sex has been changed (need disconnection by the server)..."); clif_setwaitclose(sd->fd); // forced to disconnect for the change } } else { @@ -645,11 +680,14 @@ int chrif_changedsex(int fd) * ƒAƒJƒEƒ“ƒg•Ï”•Û‘¶—v‹ *------------------------------------------ */ -int chrif_saveaccountreg2(struct map_session_data *sd) +int chrif_saveaccountreg2(struct map_session_data *sd) { int p, j; nullpo_retr(-1, sd); + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) + return -1; + p = 8; for(j = 0; j < sd->status.account_reg2_num; j++) { struct global_reg *reg = &sd->status.account_reg2[j]; @@ -671,7 +709,7 @@ int chrif_saveaccountreg2(struct map_session_data *sd) * ƒAƒJƒEƒ“ƒg•Ï”’Ê’m *------------------------------------------ */ -int chrif_accountreg2(int fd) +int chrif_accountreg2(int fd) { int j, p; struct map_session_data *sd; @@ -693,7 +731,7 @@ int chrif_accountreg2(int fd) * —£¥î•ñ“¯Šú—v‹ *------------------------------------------ */ -int chrif_divorce(int char_id, int partner_id) +int chrif_divorce(int char_id, int partner_id) { struct map_session_data *sd = NULL; @@ -719,7 +757,7 @@ int chrif_divorce(int char_id, int partner_id) * Disconnection of a player (account has been deleted in login-server) by [Yor] *------------------------------------------ */ -int chrif_accountdeletion(int fd) +int chrif_accountdeletion(int fd) { int acc; struct map_session_data *sd; @@ -731,7 +769,7 @@ int chrif_accountdeletion(int fd) if (acc > 0) { if (sd != NULL) { sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters - clif_displaymessage(sd->fd, "Your account has been deleted (disconnexion)..."); + clif_displaymessage(sd->fd, "Your account has been deleted (disconnection)..."); clif_setwaitclose(sd->fd); // forced to disconnect for the change } } else { @@ -746,7 +784,7 @@ int chrif_accountdeletion(int fd) * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor] *------------------------------------------ */ -int chrif_accountban(int fd) +int chrif_accountban(int fd) { int acc; struct map_session_data *sd; @@ -820,7 +858,7 @@ int chrif_chardisconnect(struct map_session_data *sd) { nullpo_retr(-1, sd); - if(char_fd<=0) + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) return -1; WFIFOW(char_fd,0)=0x2b18; @@ -836,10 +874,11 @@ int chrif_chardisconnect(struct map_session_data *sd) * Receiving GM accounts and their levels from char-server by [Yor] *------------------------------------------ */ -int chrif_recvgmaccounts(int fd) +int chrif_recvgmaccounts(int fd) { - printf("From login-server: receiving of %d GM accounts information.\n", pc_read_gm_account(fd)); - + sprintf(tmp_output,"From login-server: receiving information of '"CL_WHITE"%d"CL_RESET"' GM accounts.\n", pc_read_gm_account(fd)); + ShowInfo(tmp_output); + memset(tmp_output,'\0',sizeof(tmp_output)); return 0; } @@ -847,8 +886,10 @@ int chrif_recvgmaccounts(int fd) * Request to reload GM accounts and their levels: send to char-server by [Yor] *------------------------------------------ */ -int chrif_reloadGMdb(void) +int chrif_reloadGMdb(void) { + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) + return -1; WFIFOW(char_fd,0) = 0x2af7; WFIFOSET(char_fd, 2); @@ -860,12 +901,15 @@ int chrif_reloadGMdb(void) * Send rates and motd to char server [Wizputer] *------------------------------------------ */ - int chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate) + int chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate) { char buf[256]; FILE *fp; int i; + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) + return -1; + WFIFOW(char_fd,0) = 0x2b16; WFIFOW(char_fd,2) = base_rate; WFIFOW(char_fd,4) = job_rate; @@ -897,14 +941,62 @@ int chrif_reloadGMdb(void) *----------------------------------------- */ -int chrif_char_offline(struct map_session_data *sd) +int chrif_char_offline(struct map_session_data *sd) { - if (char_fd < 0) + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) return -1; WFIFOW(char_fd,0) = 0x2b17; WFIFOL(char_fd,2) = sd->status.char_id; - WFIFOSET(char_fd,6); + WFIFOL(char_fd,6) = sd->status.account_id; + WFIFOSET(char_fd,10); + + return 0; +} + +/*========================================= + * Tell char-server to reset all chars offline [Wizputer] + *----------------------------------------- + */ +int chrif_flush_fifo(void) { + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) + return -1; + + set_nonblocking(char_fd, 0); + flush_fifos(); + set_nonblocking(char_fd, 1); + + return 0; +} + +/*========================================= + * Tell char-server to reset all chars offline [Wizputer] + *----------------------------------------- + */ +int chrif_char_reset_offline(void) { + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) + return -1; + + WFIFOW(char_fd,0) = 0x2b18; + WFIFOSET(char_fd,2); + + return 0; +} + +/*========================================= + * Tell char-server charcter is online [Wizputer] + *----------------------------------------- + */ + +int chrif_char_online(struct map_session_data *sd) +{ + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) + return -1; + + WFIFOW(char_fd,0) = 0x2b19; + WFIFOL(char_fd,2) = sd->status.char_id; + WFIFOL(char_fd,6) = sd->status.account_id; + WFIFOSET(char_fd,10); return 0; } @@ -913,16 +1005,39 @@ int chrif_char_offline(struct map_session_data *sd) * *------------------------------------------ */ -int chrif_parse(int fd) +int chrif_disconnect_sub(struct map_session_data* sd,va_list va) { + clif_authfail_fd(sd->fd,1); + map_quit(sd); + return 0; +} + +int chrif_disconnect(int fd) { + if(fd == char_fd) { + char_fd = 0; + sprintf(tmp_output,"Map Server disconnected from Char Server.\n\n"); + ShowWarning(tmp_output); + clif_foreachclient(chrif_disconnect_sub); + chrif_connected = 0; + // ‘¼‚Ìmap ŽI‚̃f[ƒ^‚ðÁ‚· + map_eraseallipport(); + } + close(fd); + return 0; +} + +/*========================================== + * + *------------------------------------------ + */ +int chrif_parse(int fd) { int packet_len, cmd; - // only char-server can have an access to here. // so, if it isn't the char-server, we disconnect the session (fd != char_fd). if (fd != char_fd || session[fd]->eof) { - if (fd == char_fd) { - printf("Map-server can't connect to char-server (connection #%d).\n", fd); - char_fd = -1; + if (fd == char_fd && chrif_connected == 1) { + chrif_disconnect (fd); +// check_connect_char_server(0, 0, 0, 0); } close(fd); delete_session(fd); @@ -956,11 +1071,11 @@ int chrif_parse(int fd) case 0x2afb: chrif_sendmapack(fd); break; case 0x2afd: pc_authok(RFIFOL(fd,4), RFIFOL(fd,8), (time_t)RFIFOL(fd,12), (struct mmo_charstatus*)RFIFOP(fd,16)); break; case 0x2afe: pc_authfail(RFIFOL(fd,2)); break; - case 0x2b00: map_setusers(RFIFOL(fd,2)); break; + case 0x2b00: map_setusers(fd); break; case 0x2b03: clif_charselectok(RFIFOL(fd,2)); break; case 0x2b04: chrif_recvmap(fd); break; case 0x2b06: chrif_changemapserverack(fd); break; - case 0x2b09: map_addchariddb(RFIFOL(fd,2), RFIFOP(fd,6)); break; + case 0x2b09: map_addchariddb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break; case 0x2b0b: chrif_changedgm(fd); break; case 0x2b0d: chrif_changedsex(fd); break; case 0x2b0f: chrif_char_ask_name_answer(fd); break; @@ -991,12 +1106,12 @@ int send_users_tochar(int tid, unsigned int tick, int id, int data) { int users = 0, i; struct map_session_data *sd; - if (char_fd <= 0 || session[char_fd] == NULL) + if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) // Thanks to Toster return 0; WFIFOW(char_fd,0) = 0x2aff; for (i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data) && sd->state.auth && + if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd->state.auth && !((battle_config.hide_GM_session || (sd->status.option & OPTION_HIDE)) && pc_isGM(sd))) { WFIFOL(char_fd,6+4*users) = sd->status.char_id; users++; @@ -1015,14 +1130,19 @@ int send_users_tochar(int tid, unsigned int tick, int id, int data) { *------------------------------------------ */ int check_connect_char_server(int tid, unsigned int tick, int id, int data) { + static int displayed = 0; if (char_fd <= 0 || session[char_fd] == NULL) { - printf("Attempt to connect to char-server...\n"); + if (!displayed) { + ShowStatus("Attempting to connect to Char Server. Please wait.\n"); + displayed = 1; + } chrif_state = 0; char_fd = make_connection(char_ip, char_port); session[char_fd]->func_parse = chrif_parse; realloc_fifo(char_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); chrif_connect(char_fd); + chrif_connected = chrif_isconnect(); #ifndef TXT_ONLY srvinfo = 0; } else { @@ -1032,7 +1152,16 @@ int check_connect_char_server(int tid, unsigned int tick, int id, int data) { } #endif /* not TXT_ONLY */ } - + if (chrif_isconnect()) displayed = 0; + return 0; +} +/*========================================== + * I—¹ + *------------------------------------------ + */ +int do_final_chrif(void) +{ + delete_session(char_fd); return 0; } diff --git a/src/map/chrif.h b/src/map/chrif.h index de20c3086..f2b258ea9 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -9,6 +9,8 @@ void chrif_setport(int); int chrif_isconnect(void); +extern int chrif_connected; + int chrif_authreq(struct map_session_data *); int chrif_save(struct map_session_data*); int chrif_charselectreq(struct map_session_data *); @@ -23,9 +25,15 @@ int chrif_saveaccountreg2(struct map_session_data *sd); int chrif_reloadGMdb(void); int chrif_ragsrvinfo(int base_rate,int job_rate, int drop_rate); int chrif_char_offline(struct map_session_data *sd); +int chrif_char_reset_offline(void); +int chrif_char_online(struct map_session_data *sd); int chrif_changesex(int id, int sex); int chrif_chardisconnect(struct map_session_data *sd); +int check_connect_char_server(int tid, unsigned int tick, int id, int data); +int do_final_chrif(void); int do_init_chrif(void); +int chrif_flush_fifo(void); + #endif diff --git a/src/map/clif.c b/src/map/clif.c index 9163671a8..c8f190c5a 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1,6 +1,7 @@ // $Id: clif.c 2200 2004-11-07 11:49:58Z Yor $ #define DUMP_UNKNOWN_PACKET 1 +#define DUMP_ALL_PACKETS 0 #include <stdio.h> #include <ctype.h> @@ -24,11 +25,13 @@ #include "../common/malloc.h" #include "../common/version.h" #include "../common/nullpo.h" +#include "../common/showmsg.h" #include "map.h" #include "chrif.h" #include "clif.h" #include "pc.h" +#include "status.h" #include "npc.h" #include "itemdb.h" #include "chat.h" @@ -52,7 +55,16 @@ #define STATE_BLIND 0x10 -static const int packet_len_table[0x220] = { +struct Clif_Config clif_config; +struct packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB]; + +#define USE_PACKET_DB(sd) \ + clif_config.enable_packet_db && sd->packet_ver == clif_config.packet_db_ver + +#define IS_PACKET_DB_VER(cmd) \ + cmd == clif_config.connect_cmd + +static const int packet_len_table[MAX_PACKET_DB] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -67,12 +79,12 @@ static const int packet_len_table[0x220] = { 3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6, #endif //#0x0080 - 7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 23, -1, -1, -1, 0, // 0x8b unknown... size 2 or 23? + 7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 2, -1, -1, -1, 0, // 0x8b changed to 2 (was 23) 7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6, 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6, 8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3, //#0x00C0 - 7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 6, 2, 27, + 7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 3, 2, 27, // 0xcd change to 3 (was 6) 3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1, 30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2, 3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10, @@ -102,13 +114,11 @@ static const int packet_len_table[0x220] = { 30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1, -1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10, //#0x200 - 26, -1, 26, 10, 18, 26, 11, 34, 14, 36, 10, 19, 0, -1, 24, 0, + 26, -1, 26, 10, 18, 26, 11, 34, 14, 36, 10, 0, 0, -1, 24, 0, // 0x20c change to 0 (was 19) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 }; -// size list for each packet version after packet version 4. -static int packet_size_table[9][0x220]; - // local define enum { ALL_CLIENT, @@ -143,6 +153,7 @@ enum { static char map_ip_str[16]; static in_addr_t map_ip; +static in_addr_t bind_ip = INADDR_ANY; static int map_port = 5121; int map_fd; char talkie_mes[80]; @@ -151,17 +162,22 @@ char talkie_mes[80]; * mapŽI‚ÌipÝ’è *------------------------------------------ */ -void clif_setip(char *ip) +void clif_setip(char *ip) { memcpy(map_ip_str, ip, 16); map_ip = inet_addr(map_ip_str); } +void clif_setbindip(char *ip) +{ + bind_ip = inet_addr(ip); +} + /*========================================== * mapŽI‚ÌportÝ’è *------------------------------------------ */ -void clif_setport(int port) +void clif_setport(int port) { map_port = port; } @@ -170,7 +186,7 @@ void clif_setport(int port) * mapŽI‚Ìip“Ç‚Ýo‚µ *------------------------------------------ */ -in_addr_t clif_getip(void) +in_addr_t clif_getip(void) { return map_ip; } @@ -179,7 +195,7 @@ in_addr_t clif_getip(void) * mapŽI‚Ìport“Ç‚Ýo‚µ *------------------------------------------ */ -int clif_getport(void) +int clif_getport(void) { return map_port; } @@ -188,13 +204,13 @@ int clif_getport(void) * *------------------------------------------ */ -int clif_countusers(void) +int clif_countusers(void) { int users = 0, i; struct map_session_data *sd; for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data) && sd && sd->state.auth && + if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd && sd->state.auth && !(battle_config.hide_GM_session && pc_isGM(sd))) users++; } @@ -205,7 +221,7 @@ int clif_countusers(void) * ‘S‚Ä‚Ìclient‚ɑ΂µ‚Äfunc()ŽÀs *------------------------------------------ */ -int clif_foreachclient(int (*func)(struct map_session_data*, va_list),...) +int clif_foreachclient(int (*func)(struct map_session_data*, va_list),...) { int i; va_list ap; @@ -213,7 +229,7 @@ int clif_foreachclient(int (*func)(struct map_session_data*, va_list),...) va_start(ap,func); for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data) && sd && sd->state.auth) + if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd && sd->state.auth) func(sd, ap); } va_end(ap); @@ -224,14 +240,13 @@ int clif_foreachclient(int (*func)(struct map_session_data*, va_list),...) * clif_send‚ÅAREA*Žw’莞—p *------------------------------------------ */ -int clif_send_sub(struct block_list *bl, va_list ap) +int clif_send_sub(struct block_list *bl, va_list ap) { - unsigned char *buf; - int len; struct block_list *src_bl; - int type; struct map_session_data *sd; - + unsigned char *buf; + int len, type; + nullpo_retr(0, bl); nullpo_retr(0, ap); nullpo_retr(0, sd = (struct map_session_data *)bl); @@ -243,27 +258,30 @@ int clif_send_sub(struct block_list *bl, va_list ap) switch(type) { case AREA_WOS: - if (bl && bl == src_bl) + if (bl == src_bl) return 0; break; case AREA_WOC: - if ((sd && sd->chatID) || (bl && bl == src_bl)) + if (sd->chatID || bl == src_bl) return 0; break; case AREA_WOSC: - if ((sd) && sd->chatID && sd->chatID == ((struct map_session_data*)src_bl)->chatID) - return 0; + { + struct map_session_data *ssd = (struct map_session_data *)src_bl; + if (ssd && sd->chatID && sd->chatID == ssd->chatID) + return 0; + } break; } - if (sd) { + if (session[sd->fd] != NULL) { if (WFIFOP(sd->fd,0) == buf) { printf("WARNING: Invalid use of clif_send function\n"); printf(" Packet x%4x use a WFIFO of a player instead of to use a buffer.\n", WBUFW(buf,0)); printf(" Please correct your code.\n"); // don't send to not move the pointer of the packet for next sessions in the loop } else { - if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version + if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version memcpy(WFIFOP(sd->fd,0), buf, len); WFIFOSET(sd->fd,len); } @@ -279,8 +297,7 @@ int clif_send_sub(struct block_list *bl, va_list ap) */ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) { int i; - struct map_session_data *sd; - struct chat_data *cd; + struct map_session_data *sd = NULL; struct party *p = NULL; struct guild *g = NULL; int x0 = 0, x1 = 0, y0 = 0, y1 = 0; @@ -288,12 +305,15 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) { if (type != ALL_CLIENT) { nullpo_retr(0, bl); } + if (bl && bl->type == BL_PC) { + nullpo_retr (0, sd=(struct map_session_data*)bl); + } switch(type) { case ALL_CLIENT: // ‘SƒNƒ‰ƒCƒAƒ“ƒg‚É‘—M for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data) != NULL && sd->state.auth) { - if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version + if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) != NULL && sd->state.auth) { + if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version memcpy(WFIFOP(i,0), buf, len); WFIFOSET(i,len); } @@ -302,8 +322,8 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) { break; case ALL_SAMEMAP: // “¯‚¶ƒ}ƒbƒv‚Ì‘SƒNƒ‰ƒCƒAƒ“ƒg‚É‘—M for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data) != NULL && sd->state.auth && sd->bl.m == bl->m) { - if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version + if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) != NULL && sd->state.auth && sd->bl.m == bl->m) { + if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version memcpy(WFIFOP(i,0), buf, len); WFIFOSET(i,len); } @@ -321,21 +341,24 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) { break; case CHAT: case CHAT_WOS: - cd = (struct chat_data*)bl; - if (bl->type == BL_PC) { - sd = (struct map_session_data*)bl; - cd = (struct chat_data*)map_id2bl(sd->chatID); - } else if (bl->type != BL_CHAT) - break; - if (cd == NULL) - break; - for(i = 0; i < cd->users; i++) { - if (type == CHAT_WOS && cd->usersd[i] == (struct map_session_data*)bl) - continue; - if (packet_size_table[cd->usersd[i]->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version - if (cd->usersd[i]->fd >=0 && session[cd->usersd[i]->fd]) // Added check to see if session exists [PoW] - memcpy(WFIFOP(cd->usersd[i]->fd,0), buf, len); - WFIFOSET(cd->usersd[i]->fd,len); + { + struct chat_data *cd; + if (sd) { + cd = (struct chat_data*)map_id2bl(sd->chatID); + } else if (bl->type == BL_CHAT) { + cd = (struct chat_data*)bl; + } else if (bl->type != BL_CHAT) + break; + if (cd == NULL) + break; + for(i = 0; i < cd->users; i++) { + if (type == CHAT_WOS && cd->usersd[i] == sd) + continue; + if (packet_db[cd->usersd[i]->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version + if (cd->usersd[i]->fd >=0 && session[cd->usersd[i]->fd]) // Added check to see if session exists [PoW] + memcpy(WFIFOP(cd->usersd[i]->fd,0), buf, len); + WFIFOSET(cd->usersd[i]->fd,len); + } } } break; @@ -350,18 +373,18 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) { case PARTY_WOS: // Ž©•ªˆÈŠO‚Ì‘Sƒp[ƒeƒB[ƒƒ“ƒo‚É‘—M case PARTY_SAMEMAP: // “¯‚¶ƒ}ƒbƒv‚Ì‘Sƒp[ƒeƒB[ƒƒ“ƒo‚É‘—M case PARTY_SAMEMAP_WOS: // Ž©•ªˆÈŠO‚Ì“¯‚¶ƒ}ƒbƒv‚Ì‘Sƒp[ƒeƒB[ƒƒ“ƒo‚É‘—M - if (bl->type == BL_PC) { - sd = (struct map_session_data *)bl; + if (sd) { if (sd->partyspy > 0) { p = party_search(sd->partyspy); - } else { - if (sd->status.party_id > 0) - p = party_search(sd->status.party_id); + } else if (sd->status.party_id > 0) { + p = party_search(sd->status.party_id); } } if (p) { for(i=0;i<MAX_PARTY;i++){ if ((sd = p->member[i].sd) != NULL) { + if ((session[sd->fd] == NULL) || (session[sd->fd]->session_data == NULL)) + continue; if (sd->bl.id == bl->id && (type == PARTY_WOS || type == PARTY_SAMEMAP_WOS || type == PARTY_AREA_WOS)) continue; @@ -371,7 +394,7 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) { (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1)) continue; - if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version + if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version memcpy(WFIFOP(sd->fd,0), buf, len); WFIFOSET(sd->fd,len); } @@ -381,9 +404,9 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) { } } for (i = 0; i < fd_max; i++){ - if (session[i] && (sd = session[i]->session_data) != NULL && sd->state.auth) { + if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) != NULL && sd->state.auth) { if (sd->partyspy == p->party_id) { - if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version + if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version memcpy(WFIFOP(sd->fd,0), buf, len); WFIFOSET(sd->fd,len); } @@ -393,8 +416,7 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) { } break; case SELF: - sd = (struct map_session_data *)bl; - if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version + if (sd && packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version memcpy(WFIFOP(sd->fd,0), buf, len); WFIFOSET(sd->fd,len); } @@ -410,13 +432,11 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) { y1 = bl->y + AREA_SIZE; case GUILD: case GUILD_WOS: - if (bl && bl->type == BL_PC) { // guildspy [Syrus22] - sd = (struct map_session_data *)bl; + if (sd) { // guildspy [Syrus22] if (sd->guildspy > 0) { g = guild_search(sd->guildspy); - } else { - if (sd->status.guild_id > 0) - g = guild_search(sd->status.guild_id); + } else if (sd->status.guild_id > 0) { + g = guild_search(sd->status.guild_id); } } if (g) { @@ -424,16 +444,18 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) { if ((sd = g->member[i].sd) != NULL) { if (type == GUILD_WOS && sd->bl.id == bl->id) continue; - if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version + if (sd->packet_ver > MAX_PACKET_VER) + continue; + if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version memcpy(WFIFOP(sd->fd,0), buf, len); WFIFOSET(sd->fd,len); } } } for (i = 0; i < fd_max; i++){ - if (session[i] && (sd = session[i]->session_data) != NULL && sd->state.auth) { + if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) != NULL && sd->state.auth) { if (sd->guildspy == g->guild_id) { - if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version + if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version memcpy(WFIFOP(sd->fd,0), buf, len); WFIFOSET(sd->fd,len); } @@ -444,10 +466,8 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) { break; case GUILD_SAMEMAP: case GUILD_SAMEMAP_WOS: - if (bl->type == BL_PC) { - sd = (struct map_session_data *)bl; - if (sd->status.guild_id > 0) - g = guild_search(sd->status.guild_id); + if (sd && sd->status.guild_id > 0) { + g = guild_search(sd->status.guild_id); } if (g) { for(i = 0; i < g->max_member; i++) { @@ -461,7 +481,7 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) { (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1)) continue; - if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version + if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version memcpy(WFIFOP(sd->fd,0), buf, len); WFIFOSET(sd->fd,len); } @@ -580,7 +600,7 @@ static int clif_set009e(struct flooritem_data *fitem,unsigned char *buf) { *------------------------------------------ */ int clif_dropflooritem(struct flooritem_data *fitem) { - char buf[64]; + unsigned char buf[64]; nullpo_retr(0, fitem); @@ -685,7 +705,7 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) { WBUFW(buf,0) = 0x78; WBUFL(buf,2) = sd->bl.id; - WBUFW(buf,6) = battle_get_speed(&sd->bl); + WBUFW(buf,6) = status_get_speed(&sd->bl); WBUFW(buf,8) = sd->opt1; WBUFW(buf,10) = sd->opt2; WBUFW(buf,12) = sd->status.option; @@ -697,7 +717,7 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) { WBUFB(buf,49) = 5; WBUFB(buf,50) = 5; WBUFB(buf,51) = 0; - WBUFW(buf,52) = ((level = battle_get_lv(&sd->bl)) > battle_config.max_lv) ? battle_config.max_lv : level; + WBUFW(buf,52) = ((level = status_get_lv(&sd->bl)) > battle_config.max_lv) ? battle_config.max_lv : level; return packet_len_table[0x78]; } @@ -775,7 +795,7 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) { WBUFB(buf,49) = 5; WBUFB(buf,50) = 5; WBUFB(buf,51) = sd->state.dead_sit; - WBUFW(buf,52) = ((level = battle_get_lv(&sd->bl)) > battle_config.max_lv) ? battle_config.max_lv : level; + WBUFW(buf,52) = ((level = status_get_lv(&sd->bl)) > battle_config.max_lv) ? battle_config.max_lv : level; return packet_len_table[0x1d8]; #endif @@ -794,7 +814,7 @@ static int clif_set007b(struct map_session_data *sd,unsigned char *buf) { WBUFW(buf,0)=0x7b; WBUFL(buf,2)=sd->bl.id; - WBUFW(buf,6)=battle_get_speed(&sd->bl); + WBUFW(buf,6)=status_get_speed(&sd->bl); WBUFW(buf,8)=sd->opt1; WBUFW(buf,10)=sd->opt2; WBUFW(buf,12)=sd->status.option; @@ -806,7 +826,7 @@ static int clif_set007b(struct map_session_data *sd,unsigned char *buf) { WBUFB(buf,55)=0; WBUFB(buf,56)=5; WBUFB(buf,57)=5; - WBUFW(buf,58)=((level = battle_get_lv(&sd->bl))>battle_config.max_lv)? battle_config.max_lv:level; + WBUFW(buf,58)=((level = status_get_lv(&sd->bl))>battle_config.max_lv)? battle_config.max_lv:level; return packet_len_table[0x7b]; } @@ -896,17 +916,17 @@ static int clif_set007b(struct map_session_data *sd,unsigned char *buf) { * ƒNƒ‰ƒXƒ`ƒFƒ“ƒW type‚ÍMob‚ÌꇂÍ1‚Å‘¼‚Í0H *------------------------------------------ */ -int clif_class_change(struct block_list *bl,int class,int type) +int clif_class_change(struct block_list *bl,int class_,int type) { - char buf[16]; + unsigned char buf[16]; nullpo_retr(0, bl); - if(class >= MAX_PC_CLASS) { + if(class_ >= MAX_PC_CLASS) { WBUFW(buf,0)=0x1b0; WBUFL(buf,2)=bl->id; WBUFB(buf,6)=type; - WBUFL(buf,7)=class; + WBUFL(buf,7)=class_; clif_send(buf,packet_len_table[0x1b0],bl,AREA); } @@ -916,9 +936,9 @@ int clif_class_change(struct block_list *bl,int class,int type) * *------------------------------------------ */ -int clif_mob_class_change(struct mob_data *md, int class) { - char buf[16]; - int view = mob_get_viewclass(class); +int clif_mob_class_change(struct mob_data *md, int class_) { + unsigned char buf[16]; + int view = mob_get_viewclass(class_); nullpo_retr(0, md); @@ -955,9 +975,9 @@ int clif_mob_equip(struct mob_data *md, int nameid) { * MOB•\ަ1 *------------------------------------------ */ -static int clif_mob0078(struct mob_data *md, unsigned char *buf) +static int clif_mob0078(struct mob_data *md, unsigned char *buf) { - int level; + int level, i; memset(buf,0,packet_len_table[0x78]); @@ -965,25 +985,25 @@ static int clif_mob0078(struct mob_data *md, unsigned char *buf) WBUFW(buf,0)=0x78; WBUFL(buf,2)=md->bl.id; - WBUFW(buf,6)=battle_get_speed(&md->bl); + WBUFW(buf,6)=status_get_speed(&md->bl); WBUFW(buf,8)=md->opt1; WBUFW(buf,10)=md->opt2; WBUFW(buf,12)=md->option; - WBUFW(buf,14)=mob_get_viewclass(md->class); - if((mob_get_viewclass(md->class) <= 23) || (mob_get_viewclass(md->class) == 812) || (mob_get_viewclass(md->class) >= 4001)) { - WBUFW(buf,12)|=mob_db[md->class].option; - WBUFW(buf,16)=mob_get_hair(md->class); - WBUFW(buf,18)=mob_get_weapon(md->class); - WBUFW(buf,20)=mob_get_head_buttom(md->class); - WBUFW(buf,22)=mob_get_shield(md->class); - WBUFW(buf,24)=mob_get_head_top(md->class); - WBUFW(buf,26)=mob_get_head_mid(md->class); - WBUFW(buf,28)=mob_get_hair_color(md->class); - WBUFW(buf,30)=mob_get_clothes_color(md->class); //Add for player monster dye - Valaris - WBUFB(buf,45)=mob_get_sex(md->class); - } - - if (md->class >= 1285 && md->class <= 1287 && md->guild_id) { // Added guardian emblems [Valaris] + WBUFW(buf,14)=mob_get_viewclass(md->class_); + if((i=mob_get_viewclass(md->class_)) <= 23 || i == 812 || i >= 4001) { + WBUFW(buf,12)|=mob_db[md->class_].option; + WBUFW(buf,16)=mob_get_hair(md->class_); + WBUFW(buf,18)=mob_get_weapon(md->class_); + WBUFW(buf,20)=mob_get_head_buttom(md->class_); + WBUFW(buf,22)=mob_get_shield(md->class_); + WBUFW(buf,24)=mob_get_head_top(md->class_); + WBUFW(buf,26)=mob_get_head_mid(md->class_); + WBUFW(buf,28)=mob_get_hair_color(md->class_); + WBUFW(buf,30)=mob_get_clothes_color(md->class_); //Add for player monster dye - Valaris + WBUFB(buf,45)=mob_get_sex(md->class_); + } + + if (md->class_ >= 1285 && md->class_ <= 1287 && md->guild_id) { // Added guardian emblems [Valaris] struct guild *g; struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name); if (gc && gc->guild_id > 0) { @@ -999,7 +1019,7 @@ static int clif_mob0078(struct mob_data *md, unsigned char *buf) WBUFB(buf,48)|=md->dir&0x0f; WBUFB(buf,49)=5; WBUFB(buf,50)=5; - WBUFW(buf,52)=((level = battle_get_lv(&md->bl))>battle_config.max_lv)? battle_config.max_lv:level; + WBUFW(buf,52)=((level = status_get_lv(&md->bl))>battle_config.max_lv)? battle_config.max_lv:level; return packet_len_table[0x78]; } @@ -1017,27 +1037,27 @@ static int clif_mob007b(struct mob_data *md, unsigned char *buf) { WBUFW(buf,0)=0x7b; WBUFL(buf,2)=md->bl.id; - WBUFW(buf,6)=battle_get_speed(&md->bl); + WBUFW(buf,6)=status_get_speed(&md->bl); WBUFW(buf,8)=md->opt1; WBUFW(buf,10)=md->opt2; WBUFW(buf,12)=md->option; - WBUFW(buf,14)=mob_get_viewclass(md->class); - if ((mob_get_viewclass(md->class) < 24) || (mob_get_viewclass(md->class) > 4000)) { - WBUFW(buf,12)|=mob_db[md->class].option; - WBUFW(buf,16)=mob_get_hair(md->class); - WBUFW(buf,18)=mob_get_weapon(md->class); - WBUFW(buf,20)=mob_get_head_buttom(md->class); + WBUFW(buf,14)=mob_get_viewclass(md->class_); + if ((mob_get_viewclass(md->class_) < 24) || (mob_get_viewclass(md->class_) > 4000)) { + WBUFW(buf,12)|=mob_db[md->class_].option; + WBUFW(buf,16)=mob_get_hair(md->class_); + WBUFW(buf,18)=mob_get_weapon(md->class_); + WBUFW(buf,20)=mob_get_head_buttom(md->class_); WBUFL(buf,22)=gettick(); - WBUFW(buf,26)=mob_get_shield(md->class); - WBUFW(buf,28)=mob_get_head_top(md->class); - WBUFW(buf,30)=mob_get_head_mid(md->class); - WBUFW(buf,32)=mob_get_hair_color(md->class); - WBUFW(buf,34)=mob_get_clothes_color(md->class); //Add for player monster dye - Valaris - WBUFB(buf,49)=mob_get_sex(md->class); + WBUFW(buf,26)=mob_get_shield(md->class_); + WBUFW(buf,28)=mob_get_head_top(md->class_); + WBUFW(buf,30)=mob_get_head_mid(md->class_); + WBUFW(buf,32)=mob_get_hair_color(md->class_); + WBUFW(buf,34)=mob_get_clothes_color(md->class_); //Add for player monster dye - Valaris + WBUFB(buf,49)=mob_get_sex(md->class_); } else WBUFL(buf,22)=gettick(); - if(md->class >= 1285 && md->class <= 1287 && md->guild_id) { // Added guardian emblems [Valaris] + if(md->class_ >= 1285 && md->class_ <= 1287 && md->guild_id) { // Added guardian emblems [Valaris] struct guild *g; struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name); if(gc && gc->guild_id > 0){ @@ -1052,7 +1072,7 @@ static int clif_mob007b(struct mob_data *md, unsigned char *buf) { WBUFPOS2(buf,50,md->bl.x,md->bl.y,md->to_x,md->to_y); WBUFB(buf,56)=5; WBUFB(buf,57)=5; - WBUFW(buf,58)=((level = battle_get_lv(&md->bl))>battle_config.max_lv)? battle_config.max_lv:level; + WBUFW(buf,58)=((level = status_get_lv(&md->bl))>battle_config.max_lv)? battle_config.max_lv:level; return packet_len_table[0x7b]; } @@ -1071,8 +1091,8 @@ static int clif_npc0078(struct npc_data *nd, unsigned char *buf) { WBUFW(buf,0)=0x78; WBUFL(buf,2)=nd->bl.id; WBUFW(buf,6)=nd->speed; - WBUFW(buf,14)=nd->class; - if ((nd->class == 722) && (nd->u.scr.guild_id > 0) && ((g=guild_search(nd->u.scr.guild_id)) != NULL)) { + WBUFW(buf,14)=nd->class_; + if ((nd->class_ == 722) && (nd->u.scr.guild_id > 0) && ((g=guild_search(nd->u.scr.guild_id)) != NULL)) { WBUFL(buf,22)=g->emblem_id; WBUFL(buf,26)=g->guild_id; } @@ -1095,8 +1115,8 @@ static int clif_npc007b(struct npc_data *nd, unsigned char *buf) { WBUFW(buf,0)=0x7b; WBUFL(buf,2)=nd->bl.id; WBUFW(buf,6)=nd->speed; - WBUFW(buf,14)=nd->class; - if ((nd->class == 722) && (nd->u.scr.guild_id > 0) && ((g=guild_search(nd->u.scr.guild_id)) != NULL)) { + WBUFW(buf,14)=nd->class_; + if ((nd->class_ == 722) && (nd->u.scr.guild_id > 0) && ((g=guild_search(nd->u.scr.guild_id)) != NULL)) { WBUFL(buf,22)=g->emblem_id; WBUFL(buf,26)=g->guild_id; } @@ -1123,18 +1143,18 @@ static int clif_pet0078(struct pet_data *pd, unsigned char *buf) { WBUFW(buf,0)=0x78; WBUFL(buf,2)=pd->bl.id; WBUFW(buf,6)=pd->speed; - WBUFW(buf,14)=mob_get_viewclass(pd->class); - if((mob_get_viewclass(pd->class) < 24) || (mob_get_viewclass(pd->class) > 4000)) { - WBUFW(buf,12)=mob_db[pd->class].option; - WBUFW(buf,16)=mob_get_hair(pd->class); - WBUFW(buf,18)=mob_get_weapon(pd->class); - WBUFW(buf,20)=mob_get_head_buttom(pd->class); - WBUFW(buf,22)=mob_get_shield(pd->class); - WBUFW(buf,24)=mob_get_head_top(pd->class); - WBUFW(buf,26)=mob_get_head_mid(pd->class); - WBUFW(buf,28)=mob_get_hair_color(pd->class); - WBUFW(buf,30)=mob_get_clothes_color(pd->class); //Add for player pet dye - Valaris - WBUFB(buf,45)=mob_get_sex(pd->class); + WBUFW(buf,14)=mob_get_viewclass(pd->class_); + if((mob_get_viewclass(pd->class_) < 24) || (mob_get_viewclass(pd->class_) > 4000)) { + WBUFW(buf,12)=mob_db[pd->class_].option; + WBUFW(buf,16)=mob_get_hair(pd->class_); + WBUFW(buf,18)=mob_get_weapon(pd->class_); + WBUFW(buf,20)=mob_get_head_buttom(pd->class_); + WBUFW(buf,22)=mob_get_shield(pd->class_); + WBUFW(buf,24)=mob_get_head_top(pd->class_); + WBUFW(buf,26)=mob_get_head_mid(pd->class_); + WBUFW(buf,28)=mob_get_hair_color(pd->class_); + WBUFW(buf,30)=mob_get_clothes_color(pd->class_); //Add for player pet dye - Valaris + WBUFB(buf,45)=mob_get_sex(pd->class_); } else { WBUFW(buf,16)=0x14; if((view = itemdb_viewid(pd->equip)) > 0) @@ -1146,7 +1166,7 @@ static int clif_pet0078(struct pet_data *pd, unsigned char *buf) { WBUFB(buf,48)|=pd->dir&0x0f; WBUFB(buf,49)=0; WBUFB(buf,50)=0; - WBUFW(buf,52)=((level = battle_get_lv(&pd->bl))>battle_config.max_lv)? battle_config.max_lv:level; + WBUFW(buf,52)=((level = status_get_lv(&pd->bl))>battle_config.max_lv)? battle_config.max_lv:level; return packet_len_table[0x78]; } @@ -1165,19 +1185,19 @@ static int clif_pet007b(struct pet_data *pd, unsigned char *buf) { WBUFW(buf,0)=0x7b; WBUFL(buf,2)=pd->bl.id; WBUFW(buf,6)=pd->speed; - WBUFW(buf,14)=mob_get_viewclass(pd->class); - if((mob_get_viewclass(pd->class) < 24) || (mob_get_viewclass(pd->class) > 4000)) { - WBUFW(buf,12)=mob_db[pd->class].option; - WBUFW(buf,16)=mob_get_hair(pd->class); - WBUFW(buf,18)=mob_get_weapon(pd->class); - WBUFW(buf,20)=mob_get_head_buttom(pd->class); + WBUFW(buf,14)=mob_get_viewclass(pd->class_); + if((mob_get_viewclass(pd->class_) < 24) || (mob_get_viewclass(pd->class_) > 4000)) { + WBUFW(buf,12)=mob_db[pd->class_].option; + WBUFW(buf,16)=mob_get_hair(pd->class_); + WBUFW(buf,18)=mob_get_weapon(pd->class_); + WBUFW(buf,20)=mob_get_head_buttom(pd->class_); WBUFL(buf,22)=gettick(); - WBUFW(buf,26)=mob_get_shield(pd->class); - WBUFW(buf,28)=mob_get_head_top(pd->class); - WBUFW(buf,30)=mob_get_head_mid(pd->class); - WBUFW(buf,32)=mob_get_hair_color(pd->class); - WBUFW(buf,34)=mob_get_clothes_color(pd->class); //Add for player pet dye - Valaris - WBUFB(buf,49)=mob_get_sex(pd->class); + WBUFW(buf,26)=mob_get_shield(pd->class_); + WBUFW(buf,28)=mob_get_head_top(pd->class_); + WBUFW(buf,30)=mob_get_head_mid(pd->class_); + WBUFW(buf,32)=mob_get_hair_color(pd->class_); + WBUFW(buf,34)=mob_get_clothes_color(pd->class_); //Add for player pet dye - Valaris + WBUFB(buf,49)=mob_get_sex(pd->class_); } else { WBUFW(buf,16)=0x14; if ((view = itemdb_viewid(pd->equip)) > 0) @@ -1189,7 +1209,7 @@ static int clif_pet007b(struct pet_data *pd, unsigned char *buf) { WBUFPOS2(buf,50,pd->bl.x,pd->bl.y,pd->to_x,pd->to_y); WBUFB(buf,56)=0; WBUFB(buf,57)=0; - WBUFW(buf,58)=((level = battle_get_lv(&pd->bl))>battle_config.max_lv)? battle_config.max_lv:level; + WBUFW(buf,58)=((level = status_get_lv(&pd->bl))>battle_config.max_lv)? battle_config.max_lv:level; return packet_len_table[0x7b]; } @@ -1281,11 +1301,11 @@ int clif_spawnpc(struct map_session_data *sd) { clif_guild_emblem(sd,g); } // end addition [Valaris] - if (sd->status.class==13 || sd->status.class==21 || sd->status.class==4014 || sd->status.class==4022) + if (sd->status.class_==13 || sd->status.class_==21 || sd->status.class_==4014 || sd->status.class_==4022) pc_setoption(sd,sd->status.option|0x0020); // [Valaris] - if ((pc_isriding(sd) && pc_checkskill(sd,KN_RIDING)>0) && (sd->status.class==7 || - sd->status.class==14 || sd->status.class==4008 || sd->status.class==4015)) + if ((pc_isriding(sd) && pc_checkskill(sd,KN_RIDING)>0) && (sd->status.class_==7 || + sd->status.class_==14 || sd->status.class_==4008 || sd->status.class_==4015)) pc_setriding(sd); // update peco riders for people upgrading athena [Valaris] @@ -1314,7 +1334,7 @@ int clif_spawnnpc(struct npc_data *nd) nullpo_retr(0, nd); - if(nd->class < 0 || nd->flag&1 || nd->class == INVISIBLE_CLASS) + if(nd->class_ < 0 || nd->flag&1 || nd->class_ == INVISIBLE_CLASS) return 0; memset(buf,0,packet_len_table[0x7c]); @@ -1322,7 +1342,7 @@ int clif_spawnnpc(struct npc_data *nd) WBUFW(buf,0)=0x7c; WBUFL(buf,2)=nd->bl.id; WBUFW(buf,6)=nd->speed; - WBUFW(buf,20)=nd->class; + WBUFW(buf,20)=nd->class_; WBUFPOS(buf,36,nd->bl.x,nd->bl.y); clif_send(buf,packet_len_table[0x7c],&nd->bl,AREA); @@ -1344,7 +1364,7 @@ int clif_spawnmob(struct mob_data *md) nullpo_retr(0, md); - if (mob_get_viewclass(md->class) > 23 ) { + if (mob_get_viewclass(md->class_) > 23) { memset(buf,0,packet_len_table[0x7c]); WBUFW(buf,0)=0x7c; @@ -1353,7 +1373,7 @@ int clif_spawnmob(struct mob_data *md) WBUFW(buf,8)=md->opt1; WBUFW(buf,10)=md->opt2; WBUFW(buf,12)=md->option; - WBUFW(buf,20)=mob_get_viewclass(md->class); + WBUFW(buf,20)=mob_get_viewclass(md->class_); WBUFPOS(buf,36,md->bl.x,md->bl.y); clif_send(buf,packet_len_table[0x7c],&md->bl,AREA); } @@ -1361,8 +1381,8 @@ int clif_spawnmob(struct mob_data *md) len = clif_mob0078(md,buf); clif_send(buf,len,&md->bl,AREA); - if (mob_get_equip(md->class) > 0) // mob equipment [Valaris] - clif_mob_equip(md,mob_get_equip(md->class)); + if (mob_get_equip(md->class_) > 0) // mob equipment [Valaris] + clif_mob_equip(md,mob_get_equip(md->class_)); if(md->size==2) // tiny/big mobs [Valaris] clif_specialeffect(&md->bl,423,0); @@ -1385,13 +1405,13 @@ int clif_spawnpet(struct pet_data *pd) nullpo_retr(0, pd); - if (mob_get_viewclass(pd->class) >= MAX_PC_CLASS) { + if (mob_get_viewclass(pd->class_) >= MAX_PC_CLASS) { memset(buf,0,packet_len_table[0x7c]); WBUFW(buf,0)=0x7c; WBUFL(buf,2)=pd->bl.id; WBUFW(buf,6)=pd->speed; - WBUFW(buf,20)=mob_get_viewclass(pd->class); + WBUFW(buf,20)=mob_get_viewclass(pd->class_); WBUFPOS(buf,36,pd->bl.x,pd->bl.y); clif_send(buf,packet_len_table[0x7c],&pd->bl,AREA); @@ -1517,6 +1537,7 @@ static int clif_waitclose(int tid, unsigned int tick, int id, int data) { if (session[id]) session[id]->eof = 1; + close(id); return 0; } @@ -1528,7 +1549,7 @@ void clif_setwaitclose(int fd) { struct map_session_data *sd; // if player is not already in the game (double connection probably) - if ((sd = session[fd]->session_data) == NULL) { + if ((sd = (struct map_session_data*)session[fd]->session_data) == NULL) { // limited timer, just to send information. add_timer(gettick() + 1000, clif_waitclose, fd, 0); } else @@ -1584,7 +1605,7 @@ int clif_changemapserver(struct map_session_data *sd, char *mapname, int x, int *------------------------------------------ */ int clif_fixpos(struct block_list *bl) { - char buf[16]; + unsigned char buf[16]; nullpo_retr(0, bl); @@ -1690,7 +1711,7 @@ int clif_scriptmes(struct map_session_data *sd, int npcid, char *mes) { WFIFOW(fd,0)=0xb4; WFIFOW(fd,2)=strlen(mes)+9; WFIFOL(fd,4)=npcid; - strcpy(WFIFOP(fd,8),mes); + strcpy((char*)WFIFOP(fd,8),mes); WFIFOSET(fd,WFIFOW(fd,2)); return 0; @@ -1743,7 +1764,7 @@ int clif_scriptmenu(struct map_session_data *sd, int npcid, char *mes) { WFIFOW(fd,0)=0xb7; WFIFOW(fd,2)=strlen(mes)+8; WFIFOL(fd,4)=npcid; - strcpy(WFIFOP(fd,8),mes); + strcpy((char*)WFIFOP(fd,8),mes); WFIFOSET(fd,WFIFOW(fd,2)); return 0; @@ -1816,7 +1837,7 @@ int clif_cutin(struct map_session_data *sd, char *image, int type) { fd=sd->fd; WFIFOW(fd,0)=0x1b3; - memcpy(WFIFOP(fd,2),image,64); + strncpy((char*)WFIFOP(fd,2),image,64); WFIFOB(fd,66)=type; WFIFOSET(fd,packet_len_table[0x1b3]); @@ -2067,9 +2088,9 @@ int clif_storageitemlist(struct map_session_data *sd,struct storage *stor) #if PACKETVER < 5 WBUFW(buf,0)=0xa5; for(i=0,n=0;i<MAX_STORAGE;i++){ - if(stor->storage[i].nameid<=0) + if(stor->storage_[i].nameid<=0) continue; - nullpo_retr(0, id = itemdb_search(stor->storage[i].nameid)); + nullpo_retr(0, id = itemdb_search(stor->storage_[i].nameid)); if(itemdb_isequip2(id)) continue; @@ -2077,10 +2098,10 @@ int clif_storageitemlist(struct map_session_data *sd,struct storage *stor) if(id->view_id > 0) WBUFW(buf,n*10+6)=id->view_id; else - WBUFW(buf,n*10+6)=stor->storage[i].nameid; + WBUFW(buf,n*10+6)=stor->storage_[i].nameid; WBUFB(buf,n*10+8)=id->type;; - WBUFB(buf,n*10+9)=stor->storage[i].identify; - WBUFW(buf,n*10+10)=stor->storage[i].amount; + WBUFB(buf,n*10+9)=stor->storage_[i].identify; + WBUFW(buf,n*10+10)=stor->storage_[i].amount; WBUFW(buf,n*10+12)=0; n++; } @@ -2091,9 +2112,9 @@ int clif_storageitemlist(struct map_session_data *sd,struct storage *stor) #else WBUFW(buf,0)=0x1f0; for(i=0,n=0;i<MAX_STORAGE;i++){ - if(stor->storage[i].nameid<=0) + if(stor->storage_[i].nameid<=0) continue; - nullpo_retr(0, id = itemdb_search(stor->storage[i].nameid)); + nullpo_retr(0, id = itemdb_search(stor->storage_[i].nameid)); if(itemdb_isequip2(id)) continue; @@ -2101,15 +2122,15 @@ int clif_storageitemlist(struct map_session_data *sd,struct storage *stor) if(id->view_id > 0) WBUFW(buf,n*18+6)=id->view_id; else - WBUFW(buf,n*18+6)=stor->storage[i].nameid; + WBUFW(buf,n*18+6)=stor->storage_[i].nameid; WBUFB(buf,n*18+8)=id->type;; - WBUFB(buf,n*18+9)=stor->storage[i].identify; - WBUFW(buf,n*18+10)=stor->storage[i].amount; + WBUFB(buf,n*18+9)=stor->storage_[i].identify; + WBUFW(buf,n*18+10)=stor->storage_[i].amount; WBUFW(buf,n*18+12)=0; - WBUFW(buf,n*18+14)=stor->storage[i].card[0]; - WBUFW(buf,n*18+16)=stor->storage[i].card[1]; - WBUFW(buf,n*18+18)=stor->storage[i].card[2]; - WBUFW(buf,n*18+20)=stor->storage[i].card[3]; + WBUFW(buf,n*18+14)=stor->storage_[i].card[0]; + WBUFW(buf,n*18+16)=stor->storage_[i].card[1]; + WBUFW(buf,n*18+18)=stor->storage_[i].card[2]; + WBUFW(buf,n*18+20)=stor->storage_[i].card[3]; n++; } if(n){ @@ -2137,44 +2158,44 @@ int clif_storageequiplist(struct map_session_data *sd,struct storage *stor) buf = WFIFOP(fd,0); WBUFW(buf,0)=0xa6; for(i=0,n=0;i<MAX_STORAGE;i++){ - if(stor->storage[i].nameid<=0) + if(stor->storage_[i].nameid<=0) continue; - nullpo_retr(0, id = itemdb_search(stor->storage[i].nameid)); + nullpo_retr(0, id = itemdb_search(stor->storage_[i].nameid)); if(!itemdb_isequip2(id)) continue; WBUFW(buf,n*20+4)=i+1; if(id->view_id > 0) WBUFW(buf,n*20+6)=id->view_id; else - WBUFW(buf,n*20+6)=stor->storage[i].nameid; + WBUFW(buf,n*20+6)=stor->storage_[i].nameid; WBUFB(buf,n*20+8)=id->type; - WBUFB(buf,n*20+9)=stor->storage[i].identify; + WBUFB(buf,n*20+9)=stor->storage_[i].identify; WBUFW(buf,n*20+10)=id->equip; - WBUFW(buf,n*20+12)=stor->storage[i].equip; - WBUFB(buf,n*20+14)=stor->storage[i].attribute; - WBUFB(buf,n*20+15)=stor->storage[i].refine; - if(stor->storage[i].card[0]==0x00ff || stor->storage[i].card[0]==0x00fe || stor->storage[i].card[0]==(short)0xff00) { - WBUFW(buf,n*20+16)=stor->storage[i].card[0]; - WBUFW(buf,n*20+18)=stor->storage[i].card[1]; - WBUFW(buf,n*20+20)=stor->storage[i].card[2]; - WBUFW(buf,n*20+22)=stor->storage[i].card[3]; + WBUFW(buf,n*20+12)=stor->storage_[i].equip; + WBUFB(buf,n*20+14)=stor->storage_[i].attribute; + WBUFB(buf,n*20+15)=stor->storage_[i].refine; + if(stor->storage_[i].card[0]==0x00ff || stor->storage_[i].card[0]==0x00fe || stor->storage_[i].card[0]==(short)0xff00) { + WBUFW(buf,n*20+16)=stor->storage_[i].card[0]; + WBUFW(buf,n*20+18)=stor->storage_[i].card[1]; + WBUFW(buf,n*20+20)=stor->storage_[i].card[2]; + WBUFW(buf,n*20+22)=stor->storage_[i].card[3]; } else { - if(stor->storage[i].card[0] > 0 && (j=itemdb_viewid(stor->storage[i].card[0])) > 0) + if(stor->storage_[i].card[0] > 0 && (j=itemdb_viewid(stor->storage_[i].card[0])) > 0) WBUFW(buf,n*20+16)=j; else - WBUFW(buf,n*20+16)=stor->storage[i].card[0]; - if(stor->storage[i].card[1] > 0 && (j=itemdb_viewid(stor->storage[i].card[1])) > 0) + WBUFW(buf,n*20+16)=stor->storage_[i].card[0]; + if(stor->storage_[i].card[1] > 0 && (j=itemdb_viewid(stor->storage_[i].card[1])) > 0) WBUFW(buf,n*20+18)=j; else - WBUFW(buf,n*20+18)=stor->storage[i].card[1]; - if(stor->storage[i].card[2] > 0 && (j=itemdb_viewid(stor->storage[i].card[2])) > 0) + WBUFW(buf,n*20+18)=stor->storage_[i].card[1]; + if(stor->storage_[i].card[2] > 0 && (j=itemdb_viewid(stor->storage_[i].card[2])) > 0) WBUFW(buf,n*20+20)=j; else - WBUFW(buf,n*20+20)=stor->storage[i].card[2]; - if(stor->storage[i].card[3] > 0 && (j=itemdb_viewid(stor->storage[i].card[3])) > 0) + WBUFW(buf,n*20+20)=stor->storage_[i].card[2]; + if(stor->storage_[i].card[3] > 0 && (j=itemdb_viewid(stor->storage_[i].card[3])) > 0) WBUFW(buf,n*20+22)=j; else - WBUFW(buf,n*20+22)=stor->storage[i].card[3]; + WBUFW(buf,n*20+22)=stor->storage_[i].card[3]; } n++; } @@ -2204,9 +2225,9 @@ int clif_guildstorageitemlist(struct map_session_data *sd,struct guild_storage * #if PACKETVER < 5 WBUFW(buf,0)=0xa5; for(i=0,n=0;i<MAX_GUILD_STORAGE;i++){ - if(stor->storage[i].nameid<=0) + if(stor->storage_[i].nameid<=0) continue; - nullpo_retr(0, id = itemdb_search(stor->storage[i].nameid)); + nullpo_retr(0, id = itemdb_search(stor->storage_[i].nameid)); if(itemdb_isequip2(id)) continue; @@ -2214,10 +2235,10 @@ int clif_guildstorageitemlist(struct map_session_data *sd,struct guild_storage * if(id->view_id > 0) WBUFW(buf,n*10+6)=id->view_id; else - WBUFW(buf,n*10+6)=stor->storage[i].nameid; + WBUFW(buf,n*10+6)=stor->storage_[i].nameid; WBUFB(buf,n*10+8)=id->type;; - WBUFB(buf,n*10+9)=stor->storage[i].identify; - WBUFW(buf,n*10+10)=stor->storage[i].amount; + WBUFB(buf,n*10+9)=stor->storage_[i].identify; + WBUFW(buf,n*10+10)=stor->storage_[i].amount; WBUFW(buf,n*10+12)=0; n++; } @@ -2228,9 +2249,9 @@ int clif_guildstorageitemlist(struct map_session_data *sd,struct guild_storage * #else WBUFW(buf,0)=0x1f0; for(i=0,n=0;i<MAX_GUILD_STORAGE;i++){ - if(stor->storage[i].nameid<=0) + if(stor->storage_[i].nameid<=0) continue; - nullpo_retr(0, id = itemdb_search(stor->storage[i].nameid)); + nullpo_retr(0, id = itemdb_search(stor->storage_[i].nameid)); if(itemdb_isequip2(id)) continue; @@ -2238,15 +2259,15 @@ int clif_guildstorageitemlist(struct map_session_data *sd,struct guild_storage * if(id->view_id > 0) WBUFW(buf,n*18+6)=id->view_id; else - WBUFW(buf,n*18+6)=stor->storage[i].nameid; + WBUFW(buf,n*18+6)=stor->storage_[i].nameid; WBUFB(buf,n*18+8)=id->type;; - WBUFB(buf,n*18+9)=stor->storage[i].identify; - WBUFW(buf,n*18+10)=stor->storage[i].amount; + WBUFB(buf,n*18+9)=stor->storage_[i].identify; + WBUFW(buf,n*18+10)=stor->storage_[i].amount; WBUFW(buf,n*18+12)=0; - WBUFW(buf,n*18+14)=stor->storage[i].card[0]; - WBUFW(buf,n*18+16)=stor->storage[i].card[1]; - WBUFW(buf,n*18+18)=stor->storage[i].card[2]; - WBUFW(buf,n*18+20)=stor->storage[i].card[3]; + WBUFW(buf,n*18+14)=stor->storage_[i].card[0]; + WBUFW(buf,n*18+16)=stor->storage_[i].card[1]; + WBUFW(buf,n*18+18)=stor->storage_[i].card[2]; + WBUFW(buf,n*18+20)=stor->storage_[i].card[3]; n++; } if(n){ @@ -2274,44 +2295,44 @@ int clif_guildstorageequiplist(struct map_session_data *sd,struct guild_storage WBUFW(buf,0)=0xa6; for(i=0,n=0;i<MAX_GUILD_STORAGE;i++){ - if(stor->storage[i].nameid<=0) + if(stor->storage_[i].nameid<=0) continue; - nullpo_retr(0, id = itemdb_search(stor->storage[i].nameid)); + nullpo_retr(0, id = itemdb_search(stor->storage_[i].nameid)); if(!itemdb_isequip2(id)) continue; WBUFW(buf,n*20+4)=i+1; if(id->view_id > 0) WBUFW(buf,n*20+6)=id->view_id; else - WBUFW(buf,n*20+6)=stor->storage[i].nameid; + WBUFW(buf,n*20+6)=stor->storage_[i].nameid; WBUFB(buf,n*20+8)=id->type; - WBUFB(buf,n*20+9)=stor->storage[i].identify; + WBUFB(buf,n*20+9)=stor->storage_[i].identify; WBUFW(buf,n*20+10)=id->equip; - WBUFW(buf,n*20+12)=stor->storage[i].equip; - WBUFB(buf,n*20+14)=stor->storage[i].attribute; - WBUFB(buf,n*20+15)=stor->storage[i].refine; - if(stor->storage[i].card[0]==0x00ff || stor->storage[i].card[0]==0x00fe || stor->storage[i].card[0]==(short)0xff00) { - WBUFW(buf,n*20+16)=stor->storage[i].card[0]; - WBUFW(buf,n*20+18)=stor->storage[i].card[1]; - WBUFW(buf,n*20+20)=stor->storage[i].card[2]; - WBUFW(buf,n*20+22)=stor->storage[i].card[3]; + WBUFW(buf,n*20+12)=stor->storage_[i].equip; + WBUFB(buf,n*20+14)=stor->storage_[i].attribute; + WBUFB(buf,n*20+15)=stor->storage_[i].refine; + if(stor->storage_[i].card[0]==0x00ff || stor->storage_[i].card[0]==0x00fe || stor->storage_[i].card[0]==(short)0xff00) { + WBUFW(buf,n*20+16)=stor->storage_[i].card[0]; + WBUFW(buf,n*20+18)=stor->storage_[i].card[1]; + WBUFW(buf,n*20+20)=stor->storage_[i].card[2]; + WBUFW(buf,n*20+22)=stor->storage_[i].card[3]; } else { - if(stor->storage[i].card[0] > 0 && (j=itemdb_viewid(stor->storage[i].card[0])) > 0) + if(stor->storage_[i].card[0] > 0 && (j=itemdb_viewid(stor->storage_[i].card[0])) > 0) WBUFW(buf,n*20+16)=j; else - WBUFW(buf,n*20+16)=stor->storage[i].card[0]; - if(stor->storage[i].card[1] > 0 && (j=itemdb_viewid(stor->storage[i].card[1])) > 0) + WBUFW(buf,n*20+16)=stor->storage_[i].card[0]; + if(stor->storage_[i].card[1] > 0 && (j=itemdb_viewid(stor->storage_[i].card[1])) > 0) WBUFW(buf,n*20+18)=j; else - WBUFW(buf,n*20+18)=stor->storage[i].card[1]; - if(stor->storage[i].card[2] > 0 && (j=itemdb_viewid(stor->storage[i].card[2])) > 0) + WBUFW(buf,n*20+18)=stor->storage_[i].card[1]; + if(stor->storage_[i].card[2] > 0 && (j=itemdb_viewid(stor->storage_[i].card[2])) > 0) WBUFW(buf,n*20+20)=j; else - WBUFW(buf,n*20+20)=stor->storage[i].card[2]; - if(stor->storage[i].card[3] > 0 && (j=itemdb_viewid(stor->storage[i].card[3])) > 0) + WBUFW(buf,n*20+20)=stor->storage_[i].card[2]; + if(stor->storage_[i].card[3] > 0 && (j=itemdb_viewid(stor->storage_[i].card[3])) > 0) WBUFW(buf,n*20+22)=j; else - WBUFW(buf,n*20+22)=stor->storage[i].card[3]; + WBUFW(buf,n*20+22)=stor->storage_[i].card[3]; } n++; } @@ -2384,6 +2405,8 @@ int clif_updatestatus(struct map_session_data *sd,int type) break; case SP_HP: WFIFOL(fd,4)=sd->status.hp; + if(battle_config.disp_hpmeter) + clif_hpmeter(sd); break; case SP_SP: WFIFOL(fd,4)=sd->status.sp; @@ -2828,7 +2851,7 @@ int clif_unequipitemack(struct map_session_data *sd,int n,int pos,int ok) */ int clif_misceffect(struct block_list* bl,int type) { - char buf[32]; + unsigned char buf[32]; nullpo_retr(0, bl); @@ -2862,7 +2885,7 @@ int clif_misceffect2(struct block_list *bl, int type) { */ int clif_changeoption(struct block_list* bl) { - char buf[32]; + unsigned char buf[32]; short option; struct status_change *sc_data; static const int omask[]={ 0x10,0x20 }; @@ -2871,18 +2894,18 @@ int clif_changeoption(struct block_list* bl) nullpo_retr(0, bl); - option = *battle_get_option(bl); - sc_data = battle_get_sc_data(bl); + option = *status_get_option(bl); + sc_data = status_get_sc_data(bl); WBUFW(buf,0) = 0x119; WBUFL(buf,2) = bl->id; - WBUFW(buf,6) = *battle_get_opt1(bl); - WBUFW(buf,8) = *battle_get_opt2(bl); + WBUFW(buf,6) = *status_get_opt1(bl); + WBUFW(buf,8) = *status_get_opt2(bl); WBUFW(buf,10) = option; WBUFB(buf,12) = 0; // ?? if(bl->type==BL_PC) { // disguises [Valaris] - struct map_session_data *sd=((struct map_session_data *)bl); + struct map_session_data *sd=(struct map_session_data *)bl; if(sd && sd->disguise > 23 && sd->disguise < 4001) { clif_send(buf,packet_len_table[0x119],bl,AREA_WOS); clif_spawnpc(sd); @@ -2895,9 +2918,9 @@ int clif_changeoption(struct block_list* bl) for(i=0;i<sizeof(omask)/sizeof(omask[0]);i++){ if( option&omask[i] ){ if( sc_data[scnum[i]].timer==-1) - skill_status_change_start(bl,scnum[i],0,0,0,0,0,0); + status_change_start(bl,scnum[i],0,0,0,0,0,0); } else { - skill_status_change_end(bl,scnum[i],-1); + status_change_end(bl,scnum[i],-1); } } @@ -2929,7 +2952,7 @@ int clif_useitemack(struct map_session_data *sd,int index,int amount,int ok) WFIFOB(fd,6)=ok; WFIFOSET(fd,packet_len_table[0xa8]); #else - char buf[32]; + unsigned char buf[32]; WBUFW(buf,0)=0x1c8; WBUFW(buf,2)=index+2; @@ -2971,19 +2994,19 @@ int clif_createchat(struct map_session_data *sd,int fail) */ int clif_dispchat(struct chat_data *cd,int fd) { - char buf[128]; // Å‘åtitle(60ƒoƒCƒg)+17 + unsigned char buf[128]; // Å‘åtitle(60ƒoƒCƒg)+17 if(cd==NULL || *cd->owner==NULL) return 1; WBUFW(buf,0)=0xd7; - WBUFW(buf,2)=strlen(cd->title)+17; + WBUFW(buf,2)=strlen((const char*)cd->title)+17; WBUFL(buf,4)=(*cd->owner)->id; WBUFL(buf,8)=cd->bl.id; WBUFW(buf,12)=cd->limit; WBUFW(buf,14)=cd->users; WBUFB(buf,16)=cd->pub; - strcpy(WBUFP(buf,17),cd->title); + strcpy((char*)WBUFP(buf,17),(const char*)cd->title); if(fd){ memcpy(WFIFOP(fd,0),buf,WBUFW(buf,2)); WFIFOSET(fd,WBUFW(buf,2)); @@ -3001,19 +3024,19 @@ int clif_dispchat(struct chat_data *cd,int fd) */ int clif_changechatstatus(struct chat_data *cd) { - char buf[128]; // Å‘åtitle(60ƒoƒCƒg)+17 + unsigned char buf[128]; // Å‘åtitle(60ƒoƒCƒg)+17 if(cd==NULL || cd->usersd[0]==NULL) return 1; WBUFW(buf,0)=0xdf; - WBUFW(buf,2)=strlen(cd->title)+17; + WBUFW(buf,2)=strlen((char*)cd->title)+17; WBUFL(buf,4)=cd->usersd[0]->bl.id; WBUFL(buf,8)=cd->bl.id; WBUFW(buf,12)=cd->limit; WBUFW(buf,14)=cd->users; WBUFB(buf,16)=cd->pub; - strcpy(WBUFP(buf,17),cd->title); + strcpy((char*)WBUFP(buf,17),(const char*)cd->title); clif_send(buf,WBUFW(buf,2),&cd->usersd[0]->bl,CHAT); return 0; @@ -3025,7 +3048,7 @@ int clif_changechatstatus(struct chat_data *cd) */ int clif_clearchat(struct chat_data *cd,int fd) { - char buf[32]; + unsigned char buf[32]; nullpo_retr(0, cd); @@ -3091,7 +3114,7 @@ int clif_joinchatok(struct map_session_data *sd,struct chat_data* cd) */ int clif_addchat(struct chat_data* cd,struct map_session_data *sd) { - char buf[32]; + unsigned char buf[32]; nullpo_retr(0, sd); nullpo_retr(0, cd); @@ -3110,7 +3133,7 @@ int clif_addchat(struct chat_data* cd,struct map_session_data *sd) */ int clif_changechatowner(struct chat_data* cd,struct map_session_data *sd) { - char buf[64]; + unsigned char buf[64]; nullpo_retr(0, sd); nullpo_retr(0, cd); @@ -3133,7 +3156,7 @@ int clif_changechatowner(struct chat_data* cd,struct map_session_data *sd) */ int clif_leavechat(struct chat_data* cd,struct map_session_data *sd) { - char buf[32]; + unsigned char buf[32]; nullpo_retr(0, sd); nullpo_retr(0, cd); @@ -3160,7 +3183,7 @@ int clif_traderequest(struct map_session_data *sd,char *name) fd=sd->fd; WFIFOW(fd,0)=0xe5; - strcpy(WFIFOP(fd,2),name); + strcpy((char*)WFIFOP(fd,2),name); WFIFOSET(fd,packet_len_table[0xe5]); return 0; @@ -3353,35 +3376,35 @@ int clif_storageitemadded(struct map_session_data *sd,struct storage *stor,int i WFIFOW(fd,0) =0xf4; // Storage item added WFIFOW(fd,2) =index+1; // index WFIFOL(fd,4) =amount; // amount - if((view = itemdb_viewid(stor->storage[index].nameid)) > 0) + if((view = itemdb_viewid(stor->storage_[index].nameid)) > 0) WFIFOW(fd,8) =view; else - WFIFOW(fd,8) =stor->storage[index].nameid; // id - WFIFOB(fd,10)=stor->storage[index].identify; //identify flag - WFIFOB(fd,11)=stor->storage[index].attribute; // attribute - WFIFOB(fd,12)=stor->storage[index].refine; //refine - if(stor->storage[index].card[0]==0x00ff || stor->storage[index].card[0]==0x00fe || stor->storage[index].card[0]==(short)0xff00) { - WFIFOW(fd,13)=stor->storage[index].card[0]; //card (4w) - WFIFOW(fd,15)=stor->storage[index].card[1]; //card (4w) - WFIFOW(fd,17)=stor->storage[index].card[2]; //card (4w) - WFIFOW(fd,19)=stor->storage[index].card[3]; //card (4w) + WFIFOW(fd,8) =stor->storage_[index].nameid; // id + WFIFOB(fd,10)=stor->storage_[index].identify; //identify flag + WFIFOB(fd,11)=stor->storage_[index].attribute; // attribute + WFIFOB(fd,12)=stor->storage_[index].refine; //refine + if(stor->storage_[index].card[0]==0x00ff || stor->storage_[index].card[0]==0x00fe || stor->storage_[index].card[0]==(short)0xff00) { + WFIFOW(fd,13)=stor->storage_[index].card[0]; //card (4w) + WFIFOW(fd,15)=stor->storage_[index].card[1]; //card (4w) + WFIFOW(fd,17)=stor->storage_[index].card[2]; //card (4w) + WFIFOW(fd,19)=stor->storage_[index].card[3]; //card (4w) } else { - if(stor->storage[index].card[0] > 0 && (j=itemdb_viewid(stor->storage[index].card[0])) > 0) + if(stor->storage_[index].card[0] > 0 && (j=itemdb_viewid(stor->storage_[index].card[0])) > 0) WFIFOW(fd,13)= j; else - WFIFOW(fd,13)= stor->storage[index].card[0]; - if(stor->storage[index].card[1] > 0 && (j=itemdb_viewid(stor->storage[index].card[1])) > 0) + WFIFOW(fd,13)= stor->storage_[index].card[0]; + if(stor->storage_[index].card[1] > 0 && (j=itemdb_viewid(stor->storage_[index].card[1])) > 0) WFIFOW(fd,15)= j; else - WFIFOW(fd,15)= stor->storage[index].card[1]; - if(stor->storage[index].card[2] > 0 && (j=itemdb_viewid(stor->storage[index].card[2])) > 0) + WFIFOW(fd,15)= stor->storage_[index].card[1]; + if(stor->storage_[index].card[2] > 0 && (j=itemdb_viewid(stor->storage_[index].card[2])) > 0) WFIFOW(fd,17)= j; else - WFIFOW(fd,17)= stor->storage[index].card[2]; - if(stor->storage[index].card[3] > 0 && (j=itemdb_viewid(stor->storage[index].card[3])) > 0) + WFIFOW(fd,17)= stor->storage_[index].card[2]; + if(stor->storage_[index].card[3] > 0 && (j=itemdb_viewid(stor->storage_[index].card[3])) > 0) WFIFOW(fd,19)= j; else - WFIFOW(fd,19)= stor->storage[index].card[3]; + WFIFOW(fd,19)= stor->storage_[index].card[3]; } WFIFOSET(fd,packet_len_table[0xf4]); @@ -3423,35 +3446,35 @@ int clif_guildstorageitemadded(struct map_session_data *sd,struct guild_storage WFIFOW(fd,0) =0xf4; // Storage item added WFIFOW(fd,2) =index+1; // index WFIFOL(fd,4) =amount; // amount - if((view = itemdb_viewid(stor->storage[index].nameid)) > 0) + if((view = itemdb_viewid(stor->storage_[index].nameid)) > 0) WFIFOW(fd,8) =view; else - WFIFOW(fd,8) =stor->storage[index].nameid; // id - WFIFOB(fd,10)=stor->storage[index].identify; //identify flag - WFIFOB(fd,11)=stor->storage[index].attribute; // attribute - WFIFOB(fd,12)=stor->storage[index].refine; //refine - if(stor->storage[index].card[0]==0x00ff || stor->storage[index].card[0]==0x00fe || stor->storage[index].card[0]==(short)0xff00) { - WFIFOW(fd,13)=stor->storage[index].card[0]; //card (4w) - WFIFOW(fd,15)=stor->storage[index].card[1]; //card (4w) - WFIFOW(fd,17)=stor->storage[index].card[2]; //card (4w) - WFIFOW(fd,19)=stor->storage[index].card[3]; //card (4w) + WFIFOW(fd,8) =stor->storage_[index].nameid; // id + WFIFOB(fd,10)=stor->storage_[index].identify; //identify flag + WFIFOB(fd,11)=stor->storage_[index].attribute; // attribute + WFIFOB(fd,12)=stor->storage_[index].refine; //refine + if(stor->storage_[index].card[0]==0x00ff || stor->storage_[index].card[0]==0x00fe || stor->storage_[index].card[0]==(short)0xff00) { + WFIFOW(fd,13)=stor->storage_[index].card[0]; //card (4w) + WFIFOW(fd,15)=stor->storage_[index].card[1]; //card (4w) + WFIFOW(fd,17)=stor->storage_[index].card[2]; //card (4w) + WFIFOW(fd,19)=stor->storage_[index].card[3]; //card (4w) } else { - if(stor->storage[index].card[0] > 0 && (j=itemdb_viewid(stor->storage[index].card[0])) > 0) + if(stor->storage_[index].card[0] > 0 && (j=itemdb_viewid(stor->storage_[index].card[0])) > 0) WFIFOW(fd,13)= j; else - WFIFOW(fd,13)= stor->storage[index].card[0]; - if(stor->storage[index].card[1] > 0 && (j=itemdb_viewid(stor->storage[index].card[1])) > 0) + WFIFOW(fd,13)= stor->storage_[index].card[0]; + if(stor->storage_[index].card[1] > 0 && (j=itemdb_viewid(stor->storage_[index].card[1])) > 0) WFIFOW(fd,15)= j; else - WFIFOW(fd,15)= stor->storage[index].card[1]; - if(stor->storage[index].card[2] > 0 && (j=itemdb_viewid(stor->storage[index].card[2])) > 0) + WFIFOW(fd,15)= stor->storage_[index].card[1]; + if(stor->storage_[index].card[2] > 0 && (j=itemdb_viewid(stor->storage_[index].card[2])) > 0) WFIFOW(fd,17)= j; else - WFIFOW(fd,17)= stor->storage[index].card[2]; - if(stor->storage[index].card[3] > 0 && (j=itemdb_viewid(stor->storage[index].card[3])) > 0) + WFIFOW(fd,17)= stor->storage_[index].card[2]; + if(stor->storage_[index].card[3] > 0 && (j=itemdb_viewid(stor->storage_[index].card[3])) > 0) WFIFOW(fd,19)= j; else - WFIFOW(fd,19)= stor->storage[index].card[3]; + WFIFOW(fd,19)= stor->storage_[index].card[3]; } WFIFOSET(fd,packet_len_table[0xf4]); @@ -3540,23 +3563,24 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds * NPC•\ަ *------------------------------------------ */ +//fixed by Valaris void clif_getareachar_npc(struct map_session_data* sd,struct npc_data* nd) { int len; - nullpo_retv(sd); nullpo_retv(nd); - - if(nd->class < 0 || nd->flag&1 || nd->class == INVISIBLE_CLASS) + if(nd->class_ < 0 || nd->flag&1 || nd->class_ == INVISIBLE_CLASS) return; - + if(nd->state.state == MS_WALK){ + len = clif_npc007b(nd,WFIFOP(sd->fd,0)); + WFIFOSET(sd->fd,len); + } else { len = clif_npc0078(nd,WFIFOP(sd->fd,0)); WFIFOSET(sd->fd,len); - + } if(nd->chat_id){ clif_dispchat((struct chat_data*)map_id2bl(nd->chat_id),sd->fd); } - } /*========================================== @@ -3573,8 +3597,8 @@ int clif_movemob(struct mob_data *md) len = clif_mob007b(md,buf); clif_send(buf,len,&md->bl,AREA); - if(mob_get_equip(md->class) > 0) // mob equipment [Valaris] - clif_mob_equip(md,mob_get_equip(md->class)); + if(mob_get_equip(md->class_) > 0) // mob equipment [Valaris] + clif_mob_equip(md,mob_get_equip(md->class_)); if(md->size==2) // tiny/big mobs [Valaris] clif_specialeffect(&md->bl,423,0); @@ -3681,12 +3705,13 @@ int clif_damage(struct block_list *src,struct block_list *dst,unsigned int tick, nullpo_retr(0, src); nullpo_retr(0, dst); - sc_data = battle_get_sc_data(dst); + sc_data = status_get_sc_data(dst); if(type != 4 && dst->type == BL_PC && ((struct map_session_data *)dst)->special_state.infinite_endure) type = 9; if(sc_data) { - if(type != 4 && sc_data[SC_ENDURE].timer != -1) + if(type != 4 && sc_data[SC_ENDURE].timer != -1 && + (dst->type == BL_PC && !map[dst->m].flag.gvg)) type = 9; if(sc_data[SC_HALLUCINATION].timer != -1) { if(damage > 0) @@ -3721,6 +3746,9 @@ void clif_getareachar_mob(struct map_session_data* sd,struct mob_data* md) nullpo_retv(sd); nullpo_retv(md); + if (session[sd->fd] == NULL) + return; + if(md->state.state == MS_WALK){ len = clif_mob007b(md,WFIFOP(sd->fd,0)); WFIFOSET(sd->fd,len); @@ -3729,14 +3757,14 @@ void clif_getareachar_mob(struct map_session_data* sd,struct mob_data* md) WFIFOSET(sd->fd,len); } - if(mob_get_equip(md->class) > 0) // mob equipment [Valaris] - clif_mob_equip(md,mob_get_equip(md->class)); + if(mob_get_equip(md->class_) > 0) // mob equipment [Valaris] + clif_mob_equip(md,mob_get_equip(md->class_)); if(md->size==2) // tiny/big mobs [Valaris] clif_specialeffect(&md->bl,423,0); else if(md->size==1) clif_specialeffect(&md->bl,421,0); - + } @@ -3868,7 +3896,7 @@ int clif_clearchar_skillunit(struct skill_unit *unit,int fd) WFIFOW(fd, 0)=0x120; WFIFOL(fd, 2)=unit->bl.id; WFIFOSET(fd,packet_len_table[0x120]); - if(unit->group->skill_id == WZ_ICEWALL) + if(unit->group && unit->group->skill_id == WZ_ICEWALL) clif_set0192(fd,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2); return 0; @@ -3880,7 +3908,7 @@ int clif_clearchar_skillunit(struct skill_unit *unit,int fd) */ int clif_01ac(struct block_list *bl) { - char buf[32]; + unsigned char buf[32]; nullpo_retr(0, bl); @@ -3904,6 +3932,9 @@ int clif_01ac(struct block_list *bl) sd=va_arg(ap,struct map_session_data*); + if (sd == NULL || session[sd->fd] == NULL) + return 0; + switch(bl->type){ case BL_PC: if(sd==(struct map_session_data*)bl) @@ -3963,7 +3994,7 @@ int clif_pcoutsight(struct block_list *bl,va_list ap) } break; case BL_NPC: - if( ((struct npc_data *)bl)->class != INVISIBLE_CLASS ) + if( ((struct npc_data *)bl)->class_ != INVISIBLE_CLASS ) clif_clearchar_id(bl->id,0,sd->fd); break; case BL_MOB: @@ -4033,7 +4064,9 @@ int clif_moboutsight(struct block_list *bl,va_list ap) nullpo_retr(0, ap); nullpo_retr(0, md=va_arg(ap,struct mob_data*)); - if(bl->type==BL_PC && (sd = (struct map_session_data*) bl)){ + if(bl->type==BL_PC + && ((sd = (struct map_session_data*) bl) != NULL) + && session[sd->fd] != NULL) { clif_clearchar_id(md->bl.id,0,sd->fd); } @@ -4053,7 +4086,9 @@ int clif_mobinsight(struct block_list *bl,va_list ap) nullpo_retr(0, ap); md=va_arg(ap,struct mob_data*); - if(bl->type==BL_PC && (sd = (struct map_session_data *)bl)){ + if(bl->type==BL_PC + && ((sd = (struct map_session_data*) bl) != NULL) + && session[sd->fd] != NULL) { clif_getareachar_mob(sd,md); } @@ -4073,7 +4108,9 @@ int clif_petoutsight(struct block_list *bl,va_list ap) nullpo_retr(0, ap); nullpo_retr(0, pd=va_arg(ap,struct pet_data*)); - if(bl->type==BL_PC && (sd = (struct map_session_data*) bl)){ + if(bl->type==BL_PC + && ((sd = (struct map_session_data*) bl) != NULL) + && session[sd->fd] != NULL) { clif_clearchar_id(pd->bl.id,0,sd->fd); } @@ -4090,7 +4127,9 @@ int clif_npcoutsight(struct block_list *bl,va_list ap) nullpo_retr(0, ap); nullpo_retr(0, nd=va_arg(ap,struct npc_data*)); - if(bl->type==BL_PC && (sd = (struct map_session_data*) bl)){ + if(bl->type==BL_PC + && ((sd = (struct map_session_data*) bl) != NULL) + && session[sd->fd] != NULL) { clif_clearchar_id(nd->bl.id,0,sd->fd); } @@ -4110,7 +4149,9 @@ int clif_petinsight(struct block_list *bl,va_list ap) nullpo_retr(0, ap); pd=va_arg(ap,struct pet_data*); - if(bl->type==BL_PC && (sd = (struct map_session_data *)bl)){ + if(bl->type==BL_PC + && ((sd = (struct map_session_data*) bl) != NULL) + && session[sd->fd] != NULL) { clif_getareachar_pet(sd,pd); } @@ -4127,7 +4168,9 @@ int clif_npcinsight(struct block_list *bl,va_list ap) nullpo_retr(0, ap); nd=va_arg(ap,struct npc_data*); - if(bl->type==BL_PC && (sd = (struct map_session_data *)bl)){ + if(bl->type==BL_PC + && ((sd = (struct map_session_data*) bl) != NULL) + && session[sd->fd] != NULL) { clif_getareachar_npc(sd,nd); } @@ -4159,14 +4202,14 @@ int clif_skillinfo(struct map_session_data *sd,int skillid,int type,int range) if(range < 0) { range = skill_get_range(id,sd->status.skill[skillid].lv); if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); + range = status_get_range(&sd->bl) - (range + 1); WFIFOW(fd,12)= range; } else WFIFOW(fd,12)= range; memset(WFIFOP(fd,14),0,24); if(!(skill_get_inf2(id)&0x01) || battle_config.quest_skill_learn == 1 || (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill) ) //WFIFOB(fd,38)= (sd->status.skill[skillid].lv < skill_get_max(id) && sd->status.skill[skillid].flag ==0 )? 1:0; - WFIFOB(fd,38)= (sd->status.skill[skillid].lv < skill_tree_get_max(id, sd->status.class) && sd->status.skill[skillid].flag ==0 )? 1:0; + WFIFOB(fd,38)= (sd->status.skill[skillid].lv < skill_tree_get_max(id, sd->status.class_) && sd->status.skill[skillid].flag ==0 )? 1:0; else WFIFOB(fd,38) = 0; WFIFOSET(fd,packet_len_table[0x147]); @@ -4196,12 +4239,12 @@ int clif_skillinfoblock(struct map_session_data *sd) WFIFOW(fd,len+8) = skill_get_sp(id,sd->status.skill[i].lv); range = skill_get_range(id,sd->status.skill[i].lv); if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); + range = status_get_range(&sd->bl) - (range + 1); WFIFOW(fd,len+10)= range; memset(WFIFOP(fd,len+12),0,24); if(!(skill_get_inf2(id)&0x01) || battle_config.quest_skill_learn == 1 || (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill) ) //WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_get_max(id) && sd->status.skill[i].flag ==0 )? 1:0; - WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_tree_get_max(id, sd->status.class) && sd->status.skill[i].flag ==0 )? 1:0; + WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_tree_get_max(id, sd->status.class_) && sd->status.skill[i].flag ==0 )? 1:0; else WFIFOB(fd,len+36) = 0; len+=37; @@ -4231,10 +4274,10 @@ int clif_skillup(struct map_session_data *sd,int skill_num) WFIFOW(fd,6) = skill_get_sp(skill_num,sd->status.skill[skill_num].lv); range = skill_get_range(skill_num,sd->status.skill[skill_num].lv); if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); + range = status_get_range(&sd->bl) - (range + 1); WFIFOW(fd,8) = range; //WFIFOB(fd,10) = (sd->status.skill[skill_num].lv < skill_get_max(sd->status.skill[skill_num].id)) ? 1 : 0; - WFIFOB(fd,10) = (sd->status.skill[skill_num].lv < skill_tree_get_max(sd->status.skill[skill_num].id, sd->status.class)) ? 1 : 0; + WFIFOB(fd,10) = (sd->status.skill[skill_num].lv < skill_tree_get_max(sd->status.skill[skill_num].id, sd->status.class_)) ? 1 : 0; WFIFOSET(fd,packet_len_table[0x10e]); return 0; @@ -4290,7 +4333,12 @@ int clif_skill_fail(struct map_session_data *sd,int skill_id,int type,int btype) fd=sd->fd; - if(type==0x4 && battle_config.display_delay_skill_fail==0){ + // reset all variables [celest] + sd->skillx = sd->skilly = -1; + sd->skillid = sd->skilllv = -1; + sd->skillitem = sd->skillitemlv = -1; + + if(type==0x4 && (battle_config.display_delay_skill_fail==0 || sd->nodelay)){ return 0; } @@ -4318,7 +4366,7 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst, nullpo_retr(0, src); nullpo_retr(0, dst); - sc_data = battle_get_sc_data(dst); + sc_data = status_get_sc_data(dst); if(type != 5 && dst->type == BL_PC && ((struct map_session_data *)dst)->special_state.infinite_endure) type = 9; @@ -4373,7 +4421,7 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst, nullpo_retr(0, src); nullpo_retr(0, dst); - sc_data = battle_get_sc_data(dst); + sc_data = status_get_sc_data(dst); if(type != 5 && dst->type == BL_PC && ((struct map_session_data *)dst)->special_state.infinite_endure) type = 9; @@ -4542,10 +4590,10 @@ int clif_skill_warppoint(struct map_session_data *sd,int skill_num, fd=sd->fd; WFIFOW(fd,0)=0x11c; WFIFOW(fd,2)=skill_num; - memcpy(WFIFOP(fd, 4),map1,16); - memcpy(WFIFOP(fd,20),map2,16); - memcpy(WFIFOP(fd,36),map3,16); - memcpy(WFIFOP(fd,52),map4,16); + strncpy((char*)WFIFOP(fd, 4),map1,16); + strncpy((char*)WFIFOP(fd,20),map2,16); + strncpy((char*)WFIFOP(fd,36),map3,16); + strncpy((char*)WFIFOP(fd,52),map4,16); WFIFOSET(fd,packet_len_table[0x11c]); return 0; } @@ -4598,14 +4646,14 @@ int clif_skill_estimation(struct map_session_data *sd,struct block_list *dst) return 0; WBUFW(buf, 0)=0x18c; - WBUFW(buf, 2)=mob_get_viewclass(md->class); + WBUFW(buf, 2)=mob_get_viewclass(md->class_); WBUFW(buf, 4)=md->level; - WBUFW(buf, 6)=mob_db[md->class].size; + WBUFW(buf, 6)=mob_db[md->class_].size; WBUFL(buf, 8)=md->hp; - WBUFW(buf,12)=battle_get_def2(&md->bl); - WBUFW(buf,14)=mob_db[md->class].race; - WBUFW(buf,16)=battle_get_mdef2(&md->bl) - (mob_db[md->class].vit>>1); - WBUFW(buf,18)=battle_get_elem_type(&md->bl); + WBUFW(buf,12)=status_get_def2(&md->bl); + WBUFW(buf,14)=mob_db[md->class_].race; + WBUFW(buf,16)=status_get_mdef2(&md->bl) - (mob_db[md->class_].vit>>1); + WBUFW(buf,18)=status_get_elem_type(&md->bl); for(i=0;i<9;i++) WBUFB(buf,20+i)= battle_attr_fix(100,i+1,md->def_ele); @@ -4668,8 +4716,11 @@ int clif_status_change(struct block_list *bl,int type,int flag) * Send message (modified by [Yor]) *------------------------------------------ */ -int clif_displaymessage(const int fd, char* mes) +int clif_displaymessage(const int fd, char* mes) { + // invalid pointer? + nullpo_retr(-1, mes); + //Console [Wizputer] if (fd == 0) printf("\033[0;36mConsole: \033[0m\033[1m%s\033[0m\n", mes); @@ -4691,13 +4742,13 @@ int clif_displaymessage(const int fd, char* mes) * “V‚̺‚ð‘—M‚·‚é *------------------------------------------ */ -int clif_GMmessage(struct block_list *bl, char* mes, int len, int flag) +int clif_GMmessage(struct block_list *bl, char* mes, int len, int flag) { unsigned char *buf; int lp; lp = (flag & 0x10) ? 8 : 4; - buf = (unsigned char*)aCalloc(len + lp, sizeof(unsigned char)); + buf = (unsigned char*)aCallocA(len + lp, sizeof(unsigned char)); WBUFW(buf,0) = 0x9a; WBUFW(buf,2) = len + lp; @@ -4710,12 +4761,33 @@ int clif_GMmessage(struct block_list *bl, char* mes, int len, int flag) (flag == 3) ? SELF : ALL_CLIENT); - if(buf) free(buf); + if(buf) aFree(buf); return 0; } /*========================================== + * ƒOƒ[ƒoƒ‹ƒƒbƒZ[ƒW + *------------------------------------------ + */ +void clif_GlobalMessage(struct block_list *bl,char *message) +{ + char buf[100]; + int len,cmd=0x8d; + + if(!bl || !message) + return; + + len=strlen(message)+1; + + WBUFW(buf,0)=cmd; + WBUFW(buf,2)=len+8; + WBUFL(buf,4)=bl->id; + strncpy((char *) WBUFP(buf,8),message,len); + clif_send((unsigned char *) buf,WBUFW(buf,2),bl,AREA_CHAT_WOC); +} + +/*========================================== * HPSP‰ñ•œƒGƒtƒFƒNƒg‚ð‘—M‚·‚é *------------------------------------------ */ @@ -4787,12 +4859,13 @@ int clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type) WFIFOL(sd->fd,10) = pvpnum; WFIFOSET(sd->fd,packet_len_table[0x19a]); } else { - char buf[32]; + unsigned char buf[32]; WBUFW(buf,0) = 0x19a; WBUFL(buf,2) = sd->bl.id; if(sd->status.option&0x46) - WBUFL(buf,6) = -1; + // WTF? a -1 to an unsigned value... + WBUFL(buf,6) = 0xFFFFFFFF; else if(pvprank<=0) pc_calc_pvprank(sd); @@ -4814,7 +4887,7 @@ int clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type) int clif_send0199(int map,int type) { struct block_list bl; - char buf[16]; + unsigned char buf[16]; bl.m = map; WBUFW(buf,0)=0x199; @@ -4845,6 +4918,8 @@ int clif_refine(int fd,struct map_session_data *sd,int fail,int index,int val) */ int clif_wis_message(int fd, char *nick, char *mes, int mes_len) // R 0097 <len>.w <nick>.24B <message>.?B { +// printf("clif_wis_message(%d, %s, %s)\n", fd, nick, mes); + WFIFOW(fd,0) = 0x97; WFIFOW(fd,2) = mes_len + 24 + 4; memcpy(WFIFOP(fd,4), nick, 24); @@ -4858,7 +4933,7 @@ int clif_wis_message(int fd, char *nick, char *mes, int mes_len) // R 0097 <len> *------------------------------------------ */ int clif_wis_end(int fd, int flag) // R 0098 <type>.B: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target -{ +{ WFIFOW(fd,0) = 0x98; WFIFOW(fd,2) = flag; WFIFOSET(fd,packet_len_table[0x98]); @@ -5076,9 +5151,9 @@ int clif_item_skill(struct map_session_data *sd,int skillid,int skilllv,const ch WFIFOW(fd,10)=skill_get_sp(skillid,skilllv); range = skill_get_range(skillid,skilllv); if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); + range = status_get_range(&sd->bl) - (range + 1); WFIFOW(fd,12)=range; - memcpy(WFIFOP(fd,14),name,24); + strncpy((char*)WFIFOP(fd,14),name,24); WFIFOB(fd,38)=0; WFIFOSET(fd,packet_len_table[0x147]); return 0; @@ -5321,7 +5396,7 @@ int clif_showvendingboard(struct block_list* bl,char *message,int fd) WBUFW(buf,0)=0x131; WBUFL(buf,2)=bl->id; - strncpy(WBUFP(buf,6),message,80); + strncpy((char*)WBUFP(buf,6),message,80); if(fd){ memcpy(WFIFOP(fd,0),buf,packet_len_table[0x131]); WFIFOSET(fd,packet_len_table[0x131]); @@ -5535,6 +5610,8 @@ int clif_party_created(struct map_session_data *sd,int flag) { int fd; + // printf("clif_party_message(%s, %d, %s)\n", p->name, account_id, mes); + nullpo_retr(0, sd); fd=sd->fd; @@ -5748,6 +5825,70 @@ int clif_party_hp(struct party *p,struct map_session_data *sd) return 0; } /*========================================== + * GM‚ÖꊂÆHP’Ê’m + *------------------------------------------ + */ +int clif_hpmeter(struct map_session_data *sd) +{ + struct map_session_data *md; + unsigned char buf[16]; + unsigned char buf2[16]; + int i; + + nullpo_retr(0, sd); + + WBUFW(buf,0)=0x107; + WBUFL(buf,2)=sd->bl.id; + WBUFW(buf,6)=sd->bl.x; + WBUFW(buf,8)=sd->bl.y; + + for(i=0;i<fd_max;i++){ + if(session[i] && (md = (struct map_session_data*)session[i]->session_data) && md->state.auth && + md->bl.m == sd->bl.m && pc_isGM(md) && sd != md){ + memcpy(WFIFOP(i,0),buf,packet_len_table[0x107]); + WFIFOSET(i,packet_len_table[0x107]); + } + } + + WBUFW(buf2,0)=0x106; + WBUFL(buf2,2)=sd->status.account_id; + WBUFW(buf2,6)=(sd->status.hp > 0x7fff)? 0x7fff:sd->status.hp; + WBUFW(buf2,8)=(sd->status.max_hp > 0x7fff)? 0x7fff:sd->status.max_hp; + for(i=0;i<fd_max;i++){ + if(session[i] && (md = (struct map_session_data*)session[i]->session_data) && md->state.auth && + md->bl.m == sd->bl.m && pc_isGM(md) && sd != md){ + memcpy(WFIFOP(i,0),buf2,packet_len_table[0x106]); + WFIFOSET(i,packet_len_table[0x106]); + } + } + + return 0; +} +/*================================================== + * Update monster hp view if it has changed [Celest] + *-------------------------------------------------- + */ +int clif_update_mobhp(struct mob_data *md) +{ + unsigned char buf[102]; + char mobhp[50]; + + nullpo_retr(0, md); + + WBUFW(buf,0) = 0x95; + WBUFL(buf,2) = md->bl.id; + + memcpy(WBUFP(buf,6), md->name, 24); + sprintf(mobhp, "hp: %d/%d", md->hp, mob_db[md->class_].max_hp); + WBUFW(buf, 0) = 0x195; + memcpy(WBUFP(buf,30), mobhp, 24); + WBUFL(buf,54) = 0; + WBUFL(buf,78) = 0; + clif_send(buf,packet_len_table[0x195],&md->bl,AREA); + + return 0; +} +/*========================================== * ƒp[ƒeƒBꊈړ®i–¢Žg—pj *------------------------------------------ */ @@ -5930,7 +6071,7 @@ int clif_pet_emotion(struct pet_data *pd,int param) if(sd->petDB->talk_convert_class < 0) return 0; else if(sd->petDB->talk_convert_class > 0) { - param -= (pd->class - 100)*100; + param -= (pd->class_ - 100)*100; param += (sd->petDB->talk_convert_class - 100)*100; } } @@ -6105,7 +6246,7 @@ int clif_combo_delay(struct block_list *bl,int wait) *------------------------------------------ */ int clif_bladestop(struct block_list *src,struct block_list *dst, - int bool) + int _bool) { unsigned char buf[32]; @@ -6115,7 +6256,7 @@ int clif_bladestop(struct block_list *src,struct block_list *dst, WBUFW(buf,0)=0x1d1; WBUFL(buf,2)=src->id; WBUFL(buf,6)=dst->id; - WBUFL(buf,10)=bool; + WBUFL(buf,10)=_bool; clif_send(buf,packet_len_table[0x1d1],src,AREA); @@ -6129,7 +6270,7 @@ int clif_bladestop(struct block_list *src,struct block_list *dst, int clif_changemapcell(int m,int x,int y,int cell_type,int type) { struct block_list bl; - char buf[32]; + unsigned char buf[32]; bl.m = m; bl.x = x; @@ -6247,6 +6388,8 @@ int clif_guild_memberlogin_notice(struct guild *g,int idx,int flag) nullpo_retr(0, g); + // printf("clif_guild_message(%s, %d, %s)\n", g->name, account_id, mes); + WBUFW(buf, 0)=0x16d; WBUFL(buf, 2)=g->member[idx].account_id; WBUFL(buf, 6)=g->member[idx].char_id; @@ -6317,32 +6460,32 @@ int clif_guild_basicinfo(struct map_session_data *sd) if(g->guild_id == gc->guild_id) t++; } - if (t==1) memcpy(WFIFOP(fd,94),"One Castle",20); - else if (t==2) memcpy(WFIFOP(fd,94),"Two Castles",20); - else if (t==3) memcpy(WFIFOP(fd,94),"Three Castles",20); - else if (t==4) memcpy(WFIFOP(fd,94),"Four Castles",20); - else if (t==5) memcpy(WFIFOP(fd,94),"Five Castles",20); - else if (t==6) memcpy(WFIFOP(fd,94),"Six Castles",20); - else if (t==7) memcpy(WFIFOP(fd,94),"Seven Castles",20); - else if (t==8) memcpy(WFIFOP(fd,94),"Eight Castles",20); - else if (t==9) memcpy(WFIFOP(fd,94),"Nine Castles",20); - else if (t==10) memcpy(WFIFOP(fd,94),"Ten Castles",20); - else if (t==11) memcpy(WFIFOP(fd,94),"Eleven Castles",20); - else if (t==12) memcpy(WFIFOP(fd,94),"Twelve Castles",20); - else if (t==13) memcpy(WFIFOP(fd,94),"Thirteen Castles",20); - else if (t==14) memcpy(WFIFOP(fd,94),"Fourteen Castles",20); - else if (t==15) memcpy(WFIFOP(fd,94),"Fifteen Castles",20); - else if (t==16) memcpy(WFIFOP(fd,94),"Sixteen Castles",20); - else if (t==17) memcpy(WFIFOP(fd,94),"Seventeen Castles",20); - else if (t==18) memcpy(WFIFOP(fd,94),"Eighteen Castles",20); - else if (t==19) memcpy(WFIFOP(fd,94),"Nineteen Castles",20); - else if (t==20) memcpy(WFIFOP(fd,94),"Twenty Castles",20); - else if (t==21) memcpy(WFIFOP(fd,94),"Twenty One Castles",20); - else if (t==22) memcpy(WFIFOP(fd,94),"Twenty Two Castles",20); - else if (t==23) memcpy(WFIFOP(fd,94),"Twenty Three Castles",20); - else if (t==24) memcpy(WFIFOP(fd,94),"Twenty Four Castles",20); - else if (t==MAX_GUILDCASTLE) memcpy(WFIFOP(fd,94),"Total Domination",20); - else memcpy(WFIFOP(fd,94),"None Taken",20); + if (t==1) strncpy((char*)WFIFOP(fd,94),"One Castle",20); + else if (t==2) strncpy((char*)WFIFOP(fd,94),"Two Castles",20); + else if (t==3) strncpy((char*)WFIFOP(fd,94),"Three Castles",20); + else if (t==4) strncpy((char*)WFIFOP(fd,94),"Four Castles",20); + else if (t==5) strncpy((char*)WFIFOP(fd,94),"Five Castles",20); + else if (t==6) strncpy((char*)WFIFOP(fd,94),"Six Castles",20); + else if (t==7) strncpy((char*)WFIFOP(fd,94),"Seven Castles",20); + else if (t==8) strncpy((char*)WFIFOP(fd,94),"Eight Castles",20); + else if (t==9) strncpy((char*)WFIFOP(fd,94),"Nine Castles",20); + else if (t==10) strncpy((char*)WFIFOP(fd,94),"Ten Castles",20); + else if (t==11) strncpy((char*)WFIFOP(fd,94),"Eleven Castles",20); + else if (t==12) strncpy((char*)WFIFOP(fd,94),"Twelve Castles",20); + else if (t==13) strncpy((char*)WFIFOP(fd,94),"Thirteen Castles",20); + else if (t==14) strncpy((char*)WFIFOP(fd,94),"Fourteen Castles",20); + else if (t==15) strncpy((char*)WFIFOP(fd,94),"Fifteen Castles",20); + else if (t==16) strncpy((char*)WFIFOP(fd,94),"Sixteen Castles",20); + else if (t==17) strncpy((char*)WFIFOP(fd,94),"Seventeen Castles",20); + else if (t==18) strncpy((char*)WFIFOP(fd,94),"Eighteen Castles",20); + else if (t==19) strncpy((char*)WFIFOP(fd,94),"Nineteen Castles",20); + else if (t==20) strncpy((char*)WFIFOP(fd,94),"Twenty Castles",20); + else if (t==21) strncpy((char*)WFIFOP(fd,94),"Twenty One Castles",20); + else if (t==22) strncpy((char*)WFIFOP(fd,94),"Twenty Two Castles",20); + else if (t==23) strncpy((char*)WFIFOP(fd,94),"Twenty Three Castles",20); + else if (t==24) strncpy((char*)WFIFOP(fd,94),"Twenty Four Castles",20); + else if (t==MAX_GUILDCASTLE) strncpy((char*)WFIFOP(fd,94),"Total Domination",20); + else strncpy((char*)WFIFOP(fd,94),"None Taken",20); WFIFOSET(fd,packet_len_table[WFIFOW(fd,0)]); clif_guild_emblem(sd,g); // Guild emblem vanish fix [Valaris] @@ -6406,7 +6549,7 @@ int clif_guild_memberlist(struct map_session_data *sd) WFIFOW(fd,c*104+12)=m->hair; WFIFOW(fd,c*104+14)=m->hair_color; WFIFOW(fd,c*104+16)=m->gender; - WFIFOW(fd,c*104+18)=m->class; + WFIFOW(fd,c*104+18)=m->class_; WFIFOW(fd,c*104+20)=m->lv; WFIFOL(fd,c*104+22)=m->exp; WFIFOL(fd,c*104+26)=m->online; @@ -6564,35 +6707,51 @@ int clif_guild_skillinfo(struct map_session_data *sd) memset(WFIFOP(fd,c*37+18),0,24); if(g->skill[i].lv < guild_skill_get_max(id)) { //Kafra and Guardian changed to require Approval [Sara] - if (g->skill[i].id == GD_KAFRACONTACT && guild_checkskill(g,GD_APPROVAL) <= 0) - up = 0; - else if (g->skill[i].id == GD_GUARDIANRESEARCH && guild_checkskill(g,GD_APPROVAL) <= 0) - up = 0; - //Glory skill requirements -- Pretty sure correct [Sara] - else if (g->skill[i].id == GD_LEADERSHIP && guild_checkskill(g,GD_GLORYGUILD) <= 0) - up = 0; - else if (g->skill[i].id == GD_GLORYWOUNDS && guild_checkskill(g,GD_GLORYGUILD) <= 0) - up = 0; - else if (g->skill[i].id == GD_SOULCOLD && guild_checkskill(g,GD_GLORYWOUNDS) <= 0) - up = 0; - else if (g->skill[i].id == GD_HAWKEYES && guild_checkskill(g,GD_LEADERSHIP) <= 0) - up = 0; - //Activated skill requirements -- Just guesses [Sara] - else if (g->skill[i].id == GD_BATTLEORDER && guild_checkskill(g,GD_APPROVAL) <= 0) - up = 0; - else if (g->skill[i].id == GD_REGENERATION && guild_checkskill(g,GD_APPROVAL) <= 0) - up = 0; - else if (g->skill[i].id == GD_RESTORE && guild_checkskill(g,GD_REGENERATION) <= 0) - up = 0; - else if (g->skill[i].id == GD_EMERGENCYCALL && guild_checkskill(g,GD_APPROVAL) <= 0) - up = 0; - if (g->skill[i].id == GD_GUARDUP && guild_checkskill(g,GD_GUARDIANRESEARCH) <= 0) - up = 0; - //Unadded yet? Has extension description in kRO tables - else if (g->skill[i].id == GD_DEVELOPMENT) - up = 0; - else - up = 1; + switch (g->skill[i].id) + { + case GD_KAFRACONTACT: + case GD_GUARDIANRESEARCH: + case GD_GUARDUP: + case GD_DEVELOPMENT: + up = guild_checkskill(g,GD_APPROVAL) > 0; + break; + case GD_LEADERSHIP: + //Glory skill requirements -- Pretty sure correct [Sara] + up = (battle_config.require_glory_guild) ? + guild_checkskill(g,GD_GLORYGUILD) > 0 : 1; + // what skill does it need now that glory guild was removed? [celest] + break; + case GD_GLORYWOUNDS: + up = (battle_config.require_glory_guild) ? + guild_checkskill(g,GD_GLORYGUILD) > 0 : 1; + break; + case GD_SOULCOLD: + up = guild_checkskill(g,GD_GLORYWOUNDS) > 0; + break; + case GD_HAWKEYES: + up = guild_checkskill(g,GD_LEADERSHIP) > 0; + break; + case GD_BATTLEORDER: + up = guild_checkskill(g,GD_APPROVAL) > 0 && + guild_checkskill(g,GD_EXTENSION) >= 2; + break; + case GD_REGENERATION: + up = guild_checkskill(g,GD_EXTENSION) >= 5 && + guild_checkskill(g,GD_BATTLEORDER) > 0; + break; + case GD_RESTORE: + up = guild_checkskill(g,GD_REGENERATION) >= 2; + break; + case GD_EMERGENCYCALL: + up = guild_checkskill(g,GD_GUARDIANRESEARCH) > 0 && + guild_checkskill(g,GD_REGENERATION) > 0; + break; + case GD_GLORYGUILD: + up = (battle_config.require_glory_guild) ? 1 : 0; + break; + default: + up = 1; + } } else { up = 0; @@ -6734,7 +6893,7 @@ int clif_guild_message(struct guild *g,int account_id,const char *mes,int len) struct map_session_data *sd; unsigned char *buf; - buf = (unsigned char*)aCalloc(len + 4, sizeof(unsigned char)); + buf = (unsigned char*)aCallocA(len + 4, sizeof(unsigned char)); WBUFW(buf, 0) = 0x17f; WBUFW(buf, 2) = len + 4; @@ -6743,7 +6902,7 @@ int clif_guild_message(struct guild *g,int account_id,const char *mes,int len) if ((sd = guild_getavailablesd(g)) != NULL) clif_send(buf, WBUFW(buf,2), &sd->bl, GUILD); - if(buf) free(buf); + if(buf) aFree(buf); return 0; } @@ -6937,10 +7096,34 @@ void clif_callpartner(struct map_session_data *sd) } */ /*========================================== + * Adopt baby [Celest] + *------------------------------------------ + */ +void clif_adopt_process(struct map_session_data *sd) +{ + int fd; + nullpo_retv(sd); + + fd=sd->fd; + WFIFOW(fd,0)=0x1f8; + WFIFOSET(fd,packet_len_table[0x1f8]); +} + +/*========================================== + * + *------------------------------------------ + */ +void clif_parse_ReqAdopt(int fd, struct map_session_data *sd) { + nullpo_retv(sd); + + printf ("%d\n", RFIFOL(fd,2)); +} + +/*========================================== * À‚é *------------------------------------------ */ -void clif_sitting(struct map_session_data *sd) +void clif_sitting(struct map_session_data *sd) { unsigned char buf[64]; @@ -6956,13 +7139,13 @@ void clif_sitting(struct map_session_data *sd) * *------------------------------------------ */ -int clif_disp_onlyself(struct map_session_data *sd, char *mes, int len) +int clif_disp_onlyself(struct map_session_data *sd, char *mes, int len) { unsigned char *buf; nullpo_retr(0, sd); - buf = (unsigned char*)aCalloc(len + 8, sizeof(unsigned char)); + buf = (unsigned char*)aCallocA(len + 8, sizeof(unsigned char)); WBUFW(buf, 0) = 0x17f; WBUFW(buf, 2) = len + 8; @@ -6970,7 +7153,7 @@ int clif_disp_onlyself(struct map_session_data *sd, char *mes, int len) clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); - if(buf) free(buf); + if(buf) aFree(buf); return 0; } @@ -6980,7 +7163,7 @@ int clif_disp_onlyself(struct map_session_data *sd, char *mes, int len) *------------------------------------------ */ -int clif_GM_kickack(struct map_session_data *sd, int id) +int clif_GM_kickack(struct map_session_data *sd, int id) { int fd; @@ -7009,6 +7192,25 @@ int clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd,int ty return 0; } + +/*========================================== + * + *------------------------------------------ + */ + +int clif_timedout(struct map_session_data *sd) +{ + nullpo_retr(0, sd); + + sprintf(tmp_output,"%sCharacter with Account ID '"CL_WHITE"%d"CL_RESET"' timed out.\n", (pc_isGM(sd))?"GM ":"", sd->bl.id); + ShowInfo(tmp_output); + map_quit(sd); + clif_authfail_fd(sd->fd,3); // Even if player is not on we still send anyway + clif_setwaitclose(sd->fd); // Set session to EOF + + return 0; +} + /*========================================== * Wis‹‘”Û‹–‰Â‰ž“š *------------------------------------------ @@ -7066,6 +7268,24 @@ void clif_soundeffect(struct map_session_data *sd,struct block_list *bl,char *na return; } + +int clif_soundeffectall(struct block_list *bl, char *name, int type) +{ + unsigned char buf[31]; + memset(buf, 0, packet_len_table[0x1d3]); + + nullpo_retr(0, bl); + + WBUFW(buf,0)=0x1d3; + memcpy(WBUFP(buf,2), name, 24); + WBUFB(buf,26)=type; + WBUFL(buf,27)=0; + WBUFL(buf,31)=bl->id; + clif_send(buf, packet_len_table[0x1d3], bl, AREA); + + return 0; +} + // displaying special effects (npcs, weather, etc) [Valaris] int clif_specialeffect(struct block_list *bl, int type, int flag) { unsigned char buf[24]; @@ -7083,8 +7303,8 @@ int clif_specialeffect(struct block_list *bl, int type, int flag) { struct map_session_data *pl_sd; int i; for(i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) != NULL && - pl_sd->state.auth && + if (session[i] && (pl_sd = (struct map_session_data*)session[i]->session_data) != NULL && + pl_sd->state.auth && (pc_isGM((struct map_session_data *)&bl) > pc_isGM((struct map_session_data *)&pl_sd->bl))) clif_specialeffect(&pl_sd->bl, type, 1); } @@ -7093,7 +7313,7 @@ int clif_specialeffect(struct block_list *bl, int type, int flag) { struct map_session_data *sd; int i; for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data) != NULL && sd->state.auth && sd->bl.m == bl->m) + if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) != NULL && sd->state.auth && sd->bl.m == bl->m) clif_specialeffect(&sd->bl, type, 1); } } @@ -7106,6 +7326,14 @@ int clif_specialeffect(struct block_list *bl, int type, int flag) { return 0; } + +// refresh the client's screen, getting rid of any effects +int clif_refresh(struct map_session_data *sd) { + nullpo_retr(-1, sd); + clif_changemap(sd,sd->mapname,sd->bl.x,sd->bl.y); + return 0; +} + // ------------ // clif_parse_* // ------------ @@ -7114,10 +7342,10 @@ int clif_specialeffect(struct block_list *bl, int type, int flag) { * *------------------------------------------ */ -void clif_parse_WantToConnection(int fd, struct map_session_data *sd) +void clif_parse_WantToConnection(int fd, struct map_session_data *sd) { struct map_session_data *old_sd; - int account_id; // account_id in the packet 0x72 or 0x7E + int cmd, account_id; // account_id in the packet 0x72 or 0x7E if (sd) { if (battle_config.error_log) @@ -7125,8 +7353,14 @@ void clif_parse_WantToConnection(int fd, struct map_session_data *sd) return; } + cmd = RFIFOW(fd,0); + + // packet DB + if (IS_PACKET_DB_VER(cmd)) { + //printf("Received bytes %d with packet 0x72.\n", RFIFOREST(fd)); + account_id = RFIFOL(fd,packet_db[clif_config.packet_db_ver][clif_config.connect_cmd].pos[0]); // 0x72 - if (RFIFOW(fd,0) == 0x72) { + } else if (cmd == 0x72) { //printf("Received bytes %d with packet 0x72.\n", RFIFOREST(fd)); if (RFIFOREST(fd) >= 39 && (RFIFOB(fd,38) == 0 || RFIFOB(fd,38) == 1)) // 00 = Female, 01 = Male account_id = RFIFOL(fd,12); @@ -7135,14 +7369,14 @@ void clif_parse_WantToConnection(int fd, struct map_session_data *sd) else // old packet version account_id = RFIFOL(fd,2); // 0x7E - } else if (RFIFOW(fd,0) == 0x7E) { + } else if (cmd == 0x7E) { //printf("Received bytes %d with packet 0x7E.\n", RFIFOREST(fd)); if (RFIFOREST(fd) >= 37 && (RFIFOB(fd,36) == 0 || RFIFOB(fd,36) == 1)) // 00 = Female, 01 = Male account_id = RFIFOL(fd,9); else account_id = RFIFOL(fd,12); // 0xF5 - } else { + } else if (cmd == 0xF5) { //printf("Received bytes %d with packet 0xF5.\n", RFIFOREST(fd)); if (RFIFOREST(fd) >= 34 && (RFIFOB(fd,33) == 0 || RFIFOB(fd,33) == 1)) // 00 = Female, 01 = Male account_id = RFIFOL(fd,7); @@ -7150,20 +7384,37 @@ void clif_parse_WantToConnection(int fd, struct map_session_data *sd) account_id = RFIFOL(fd,12); else if (RFIFOREST(fd) >= 32 && (RFIFOB(fd,31) == 0 || RFIFOB(fd,31) == 1)) // 00 = Female, 01 = Male account_id = RFIFOL(fd,10); - else // 29 28 28 - account_id = RFIFOL(fd,5); + else { // 29 28 28 // search correct value + // if account id and char id of version 14 + if (RFIFOL(fd,3) > 700000 && RFIFOL(fd,10) >= 150000 && RFIFOL(fd,10) < 5000000) // account id / char id (more than 5.000.000 characters?) [Yor] + account_id = RFIFOL(fd,3); + else + account_id = RFIFOL(fd,5); + } + // 0x9B + } else { + account_id = RFIFOL(fd,3); } // if same account already connected, we disconnect the 2 sessions if ((old_sd = map_id2sd(account_id)) != NULL) { - clif_authfail_fd(fd, 2); // same id + clif_authfail_fd(fd, 8); // still recognizes last connection clif_authfail_fd(old_sd->fd, 2); // same id + if (sd != 0) + clif_setwaitclose(sd->fd); // Set session to EOF } else { - sd = session[fd]->session_data = (struct map_session_data*)aCalloc(1, sizeof(struct map_session_data)); + sd = (struct map_session_data*)aCalloc(1, sizeof(struct map_session_data)); + session[fd]->session_data = sd; sd->fd = fd; + if (IS_PACKET_DB_VER(cmd)) { + sd->packet_ver = clif_config.packet_db_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + pc_setnewpc(sd, account_id, RFIFOL(fd,packet_db[clif_config.packet_db_ver][clif_config.connect_cmd].pos[1]), + RFIFOL(fd,packet_db[clif_config.packet_db_ver][clif_config.connect_cmd].pos[2]), + RFIFOL(fd,packet_db[clif_config.packet_db_ver][clif_config.connect_cmd].pos[3]), + RFIFOL(fd,packet_db[clif_config.packet_db_ver][clif_config.connect_cmd].pos[4]), fd); // 0x72 - if (RFIFOW(fd,0) == 0x72) { + } else if (cmd == 0x72) { if (RFIFOREST(fd) >= 39 && (RFIFOB(fd,38) == 0 || RFIFOB(fd,38) == 1)) { // 00 = Female, 01 = Male sd->packet_ver = 7; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) pc_setnewpc(sd, account_id, RFIFOL(fd,22), RFIFOL(fd,30), RFIFOL(fd,34), RFIFOB(fd,38), fd); @@ -7175,7 +7426,7 @@ void clif_parse_WantToConnection(int fd, struct map_session_data *sd) pc_setnewpc(sd, account_id, RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOB(fd,18), fd); } // 0x7E - } else if (RFIFOW(fd,0) == 0x7E) { + } else if (cmd == 0x7E) { if (RFIFOREST(fd) >= 37 && (RFIFOB(fd,36) == 0 || RFIFOB(fd,36) == 1)) { // 00 = Female, 01 = Male sd->packet_ver = 9; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) pc_setnewpc(sd, account_id, RFIFOL(fd,21), RFIFOL(fd,28), RFIFOL(fd,32), RFIFOB(fd,36), fd); @@ -7184,7 +7435,7 @@ void clif_parse_WantToConnection(int fd, struct map_session_data *sd) pc_setnewpc(sd, account_id, RFIFOL(fd,18), RFIFOL(fd,24), RFIFOL(fd,28), RFIFOB(fd,32), fd); } // 0xF5 - } else { + } else if (cmd == 0xF5) { if (RFIFOREST(fd) >= 34 && (RFIFOB(fd,33) == 0 || RFIFOB(fd,33) == 1)) { // 00 = Female, 01 = Male sd->packet_ver = 10; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) pc_setnewpc(sd, account_id, RFIFOL(fd,15), RFIFOL(fd,25), RFIFOL(fd,29), RFIFOB(fd,33), fd); @@ -7195,9 +7446,19 @@ void clif_parse_WantToConnection(int fd, struct map_session_data *sd) sd->packet_ver = 11; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) pc_setnewpc(sd, account_id, RFIFOL(fd,17), RFIFOL(fd,23), RFIFOL(fd,27), RFIFOB(fd,31), fd); } else { // 29 - sd->packet_ver = 13; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - pc_setnewpc(sd, account_id, RFIFOL(fd,14), RFIFOL(fd,20), RFIFOL(fd,24), RFIFOB(fd,28), fd); + // if account id and char id of version 14 + if (RFIFOL(fd,3) > 700000 && RFIFOL(fd,10) >= 150000 && RFIFOL(fd,10) < 5000000) { // account id / char id (more than 5.000.000 characters?) + sd->packet_ver = 15; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + pc_setnewpc(sd, account_id, RFIFOL(fd,10), RFIFOL(fd,20), RFIFOL(fd,24), RFIFOB(fd,28), fd); + } else { + sd->packet_ver = 13; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + pc_setnewpc(sd, account_id, RFIFOL(fd,14), RFIFOL(fd,20), RFIFOL(fd,24), RFIFOB(fd,28), fd); + } } + // 0x9B + } else { + sd->packet_ver = 16; // 16: 10jan05 + pc_setnewpc(sd, account_id, RFIFOL(fd,12), RFIFOL(fd,23), RFIFOL(fd,27), RFIFOB(fd,31), fd); } WFIFOL(fd,0) = sd->bl.id; @@ -7299,10 +7560,10 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if(sd->state.connect_new) { sd->state.connect_new = 0; - if(sd->status.class != sd->view_class) + if(sd->status.class_ != sd->view_class) clif_changelook(&sd->bl,LOOK_BASE,sd->view_class); if(sd->status.pet_id > 0 && sd->pd && sd->pet.intimate > 900) - clif_pet_emotion(sd->pd,(sd->pd->class - 100)*100 + 50 + pet_hungry_val(sd)); + clif_pet_emotion(sd->pd,(sd->pd->class_ - 100)*100 + 50 + pet_hungry_val(sd)); /* Stop players from spawning inside castles [Valaris] */ @@ -7326,16 +7587,17 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if(battle_config.save_clothcolor==1 && sd->status.clothes_color > 0) clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->status.clothes_color); - if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 && + //if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 && + if(sd->status.hp<sd->status.max_hp>>2 && sd->sc_data[SC_AUTOBERSERK].timer != -1 && (sd->sc_data[SC_PROVOKE].timer==-1 || sd->sc_data[SC_PROVOKE].val2==0 )) // ƒI[ƒgƒo[ƒT[ƒN”“® - skill_status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0); - + status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0); + // if(time(&timer) < ((weddingtime=pc_readglobalreg(sd,"PC_WEDDING_TIME")) + 3600)) -// skill_status_change_start(&sd->bl,SC_WEDDING,0,weddingtime,0,0,36000,0); +// status_change_start(&sd->bl,SC_WEDDING,0,weddingtime,0,0,36000,0); if(battle_config.muting_players && sd->status.manner < 0) - skill_status_change_start(&sd->bl,SC_NOCHAT,0,0,0,0,0,0); + status_change_start(&sd->bl,SC_NOCHAT,0,0,0,0,0,0); if (night_flag) { if (battle_config.night_darkness_level > 0 && !map[sd->bl.m].flag.indoors) @@ -7354,16 +7616,16 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) // option clif_changeoption(&sd->bl); if(sd->sc_data[SC_TRICKDEAD].timer != -1) - skill_status_change_end(&sd->bl,SC_TRICKDEAD,-1); + status_change_end(&sd->bl,SC_TRICKDEAD,-1); if(sd->sc_data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele)) - skill_status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1); + status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1); if(sd->special_state.infinite_endure && sd->sc_data[SC_ENDURE].timer == -1) - skill_status_change_start(&sd->bl,SC_ENDURE,10,1,0,0,0,0); + status_change_start(&sd->bl,SC_ENDURE,10,1,0,0,0,0); for(i=0;i<MAX_INVENTORY;i++){ if(sd->status.inventory[i].equip && sd->status.inventory[i].equip & 0x0002 && sd->status.inventory[i].attribute==1) - skill_status_change_start(&sd->bl,SC_BROKNWEAPON,0,0,0,0,0,0); + status_change_start(&sd->bl,SC_BROKNWEAPON,0,0,0,0,0,0); if(sd->status.inventory[i].equip && sd->status.inventory[i].equip & 0x0010 && sd->status.inventory[i].attribute==1) - skill_status_change_start(&sd->bl,SC_BROKNARMOR,0,0,0,0,0,0); + status_change_start(&sd->bl,SC_BROKNARMOR,0,0,0,0,0,0); } map_foreachinarea(clif_getareachar,sd->bl.m,sd->bl.x-AREA_SIZE,sd->bl.y-AREA_SIZE,sd->bl.x+AREA_SIZE,sd->bl.y+AREA_SIZE,0,sd); @@ -7376,29 +7638,42 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) void clif_parse_TickSend(int fd, struct map_session_data *sd) { nullpo_retv(sd); - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 8: - sd->client_tick = RFIFOL(fd,6); - break; - case 9: - sd->client_tick = RFIFOL(fd,9); - break; - case 10: - sd->client_tick = RFIFOL(fd,7); - break; - case 11: - sd->client_tick = RFIFOL(fd,10); - break; - case 12: - sd->client_tick = RFIFOL(fd,6); - break; - case 13: - sd->client_tick = RFIFOL(fd,5); - break; - default: // old version by default (and version 6 + 7) - sd->client_tick = RFIFOL(fd,2); - break; + if (USE_PACKET_DB(sd)) { + sd->client_tick=RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 8: + sd->client_tick = RFIFOL(fd,6); + break; + case 9: + sd->client_tick = RFIFOL(fd,9); + break; + case 10: + sd->client_tick = RFIFOL(fd,7); + break; + case 11: + sd->client_tick = RFIFOL(fd,10); + break; + case 12: + sd->client_tick = RFIFOL(fd,6); + break; + case 13: + case 14: + sd->client_tick = RFIFOL(fd,5); + break; + case 15: + sd->client_tick = RFIFOL(fd,3); + break; + case 16: + sd->client_tick = RFIFOL(fd,5); + break; + + default: // old version by default (and version 6 + 7) + sd->client_tick = RFIFOL(fd,2); + break; + } } + sd->server_tick = gettick(); clif_servertick(sd); } @@ -7436,7 +7711,9 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) { sd->sc_data[SC_TRICKDEAD].timer !=-1 || //Ž€‚ñ‚¾‚Ó‚è sd->sc_data[SC_BLADESTOP].timer !=-1 || //”’nŽæ‚è sd->sc_data[SC_SPIDERWEB].timer !=-1 || //ƒXƒpƒCƒ_[ƒEƒFƒbƒu - (sd->sc_data[SC_DANCING].timer !=-1 && sd->sc_data[SC_DANCING].val4)) //‡‘tƒXƒLƒ‹‰‰‘t’†‚Í“®‚¯‚È‚¢ + (sd->sc_data[SC_DANCING].timer !=-1 && sd->sc_data[SC_DANCING].val4) || //‡‘tƒXƒLƒ‹‰‰‘t’†‚Í“®‚¯‚È‚¢ + (sd->sc_data[SC_GOSPEL].timer !=-1 && sd->sc_data[SC_GOSPEL].val4 == BCT_SELF) || // cannot move while gospel is in effect + sd->sc_data[SC_CONFUSION].timer !=-1) return; if ((sd->status.option & 2) && pc_checkskill(sd, RG_TUNNELDRIVE) <= 0) return; @@ -7446,43 +7723,60 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) { pc_stopattack(sd); - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 6: - x = RFIFOB(fd,5) * 4 + (RFIFOB(fd,6) >> 6); - y = ((RFIFOB(fd,6) & 0x3f) << 4) + (RFIFOB(fd,7) >> 4); - break; - case 7: - x = RFIFOB(fd,6) * 4 + (RFIFOB(fd,7) >> 6); - y = ((RFIFOB(fd,7) & 0x3f) << 4) + (RFIFOB(fd,8) >> 4); - break; - case 8: - x = RFIFOB(fd,3) * 4 + (RFIFOB(fd,4) >> 6); - y = ((RFIFOB(fd,4) & 0x3f) << 4) + (RFIFOB(fd,5) >> 4); - break; - case 9: - x = RFIFOB(fd,12) * 4 + (RFIFOB(fd,13) >> 6); - y = ((RFIFOB(fd,13) & 0x3f) << 4) + (RFIFOB(fd,14) >> 4); - break; - case 10: - x = RFIFOB(fd,6) * 4 + (RFIFOB(fd,7) >> 6); - y = ((RFIFOB(fd,7) & 0x3f) << 4) + (RFIFOB(fd,8) >> 4); - break; - case 11: - x = RFIFOB(fd,11) * 4 + (RFIFOB(fd,12) >> 6); - y = ((RFIFOB(fd,12) & 0x3f) << 4) + (RFIFOB(fd,13) >> 4); - break; - case 12: - x = RFIFOB(fd,3) * 4 + (RFIFOB(fd,4) >> 6); - y = ((RFIFOB(fd,4) & 0x3f) << 4) + (RFIFOB(fd,5) >> 4); - break; - case 13: - x = RFIFOB(fd,3) * 4 + (RFIFOB(fd,4) >> 6); - y = ((RFIFOB(fd,4) & 0x3f) << 4) + (RFIFOB(fd,5) >> 4); - break; - default: // old version by default - x = RFIFOB(fd,2) * 4 + (RFIFOB(fd,3) >> 6); - y = ((RFIFOB(fd,3) & 0x3f) << 4) + (RFIFOB(fd,4) >> 4); - break; + if (USE_PACKET_DB(sd)) { + int cmd = RFIFOW(fd,0); + x = RFIFOB(fd,packet_db[clif_config.packet_db_ver][cmd].pos[0]) * 4 + + (RFIFOB(fd,packet_db[clif_config.packet_db_ver][cmd].pos[0] + 1) >> 6); + y = ((RFIFOB(fd,packet_db[clif_config.packet_db_ver][cmd].pos[0]+1) & 0x3f) << 4) + + (RFIFOB(fd,packet_db[clif_config.packet_db_ver][cmd].pos[0] + 2) >> 4); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 6: + x = RFIFOB(fd,5) * 4 + (RFIFOB(fd,6) >> 6); + y = ((RFIFOB(fd,6) & 0x3f) << 4) + (RFIFOB(fd,7) >> 4); + break; + case 7: + x = RFIFOB(fd,6) * 4 + (RFIFOB(fd,7) >> 6); + y = ((RFIFOB(fd,7) & 0x3f) << 4) + (RFIFOB(fd,8) >> 4); + break; + case 8: + x = RFIFOB(fd,3) * 4 + (RFIFOB(fd,4) >> 6); + y = ((RFIFOB(fd,4) & 0x3f) << 4) + (RFIFOB(fd,5) >> 4); + break; + case 9: + x = RFIFOB(fd,12) * 4 + (RFIFOB(fd,13) >> 6); + y = ((RFIFOB(fd,13) & 0x3f) << 4) + (RFIFOB(fd,14) >> 4); + break; + case 10: + x = RFIFOB(fd,6) * 4 + (RFIFOB(fd,7) >> 6); + y = ((RFIFOB(fd,7) & 0x3f) << 4) + (RFIFOB(fd,8) >> 4); + break; + case 11: + x = RFIFOB(fd,11) * 4 + (RFIFOB(fd,12) >> 6); + y = ((RFIFOB(fd,12) & 0x3f) << 4) + (RFIFOB(fd,13) >> 4); + break; + case 12: + x = RFIFOB(fd,3) * 4 + (RFIFOB(fd,4) >> 6); + y = ((RFIFOB(fd,4) & 0x3f) << 4) + (RFIFOB(fd,5) >> 4); + break; + case 13: + case 14: + x = RFIFOB(fd,3) * 4 + (RFIFOB(fd,4) >> 6); + y = ((RFIFOB(fd,4) & 0x3f) << 4) + (RFIFOB(fd,5) >> 4); + break; + case 15: + x = RFIFOB(fd,4) * 4 + (RFIFOB(fd,5) >> 6); + y = ((RFIFOB(fd,5) & 0x3f) << 4) + (RFIFOB(fd,6) >> 4); + break; + case 16: + x = RFIFOB(fd,10) * 4 + (RFIFOB(fd,11) >> 6); + y = ((RFIFOB(fd,11) & 0x3f) << 4) + (RFIFOB(fd,12) >> 4); + break; + default: // old version by default + x = RFIFOB(fd,2) * 4 + (RFIFOB(fd,3) >> 6); + y = ((RFIFOB(fd,3) & 0x3f) << 4) + (RFIFOB(fd,4) >> 4); + break; + } } pc_walktoxy(sd, x, y); @@ -7527,28 +7821,39 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) { struct block_list *bl; int account_id; - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 8: - account_id = RFIFOL(fd,11); - break; - case 9: - account_id = RFIFOL(fd,8); - break; - case 10: - account_id = RFIFOL(fd,10); - break; - case 11: - account_id = RFIFOL(fd,6); - break; - case 12: - account_id = RFIFOL(fd,11); - break; - case 13: - account_id = RFIFOL(fd,6); - break; - default: // old version by default (+ packet version 6 and 7) - account_id = RFIFOL(fd,2); - break; + if (USE_PACKET_DB(sd)) { + account_id = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 8: + account_id = RFIFOL(fd,11); + break; + case 9: + account_id = RFIFOL(fd,8); + break; + case 10: + account_id = RFIFOL(fd,10); + break; + case 11: + account_id = RFIFOL(fd,6); + break; + case 12: + account_id = RFIFOL(fd,11); + break; + case 13: + case 14: + account_id = RFIFOL(fd,6); + break; + case 15: + account_id = RFIFOL(fd,9); + break; + case 16: + account_id = RFIFOL(fd,4); + break; + default: // old version by default (+ packet version 6 and 7) + account_id = RFIFOL(fd,2); + break; + } } bl = map_id2bl(account_id); if (bl == NULL) @@ -7606,7 +7911,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) { nullpo_retv(md); memcpy(WFIFOP(fd,6), md->name, 24); - if (md->class >= 1285 && md->class <= 1288 && md->guild_id) { + if (md->class_ >= 1285 && md->class_ <= 1288 && md->guild_id) { struct guild *g; struct guild_castle *gc = guild_mapname2gc(map[md->bl.m].name); if (gc && gc->guild_id > 0 && (g = guild_search(gc->guild_id)) != NULL) { @@ -7620,7 +7925,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) { } } else if (battle_config.show_mob_hp == 1) { char mobhp[50]; - sprintf(mobhp, "hp: %d/%d", md->hp, mob_db[md->class].max_hp); + sprintf(mobhp, "hp: %d/%d", md->hp, mob_db[md->class_].max_hp); WFIFOW(fd, 0) = 0x195; memcpy(WFIFOP(fd,30), mobhp, 24); WFIFOB(fd,54) = 0; @@ -7644,42 +7949,47 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) { */ void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) { // S 008c <len>.w <str>.?B char *message; - char *buf; + unsigned char *buf; nullpo_retv(sd); - if (is_charcommand(fd, sd, RFIFOP(fd,4),0)!= CharCommand_None) return; - if ((is_atcommand(fd, sd, RFIFOP(fd,4), 0) != AtCommand_None) || - (sd->sc_data && + if ((is_atcommand(fd, sd, (char*)RFIFOP(fd,4), 0) != AtCommand_None) || + (is_charcommand(fd, sd, (char*)RFIFOP(fd,4),0)!= CharCommand_None) || + (sd->sc_data && (sd->sc_data[SC_BERSERK].timer != -1 || //ƒo[ƒT[ƒNŽž‚͉ï˜b‚à•s‰Â sd->sc_data[SC_NOCHAT].timer != -1 ))) //ƒ`ƒƒƒbƒg‹ÖŽ~ return; - message = (char*)aCalloc(RFIFOW(fd,2) + 128, sizeof(char)); - buf = (char*)aCalloc(RFIFOW(fd,2) + 4, sizeof(char)); + message = (char*)aCallocA(RFIFOW(fd,2) + 128, sizeof(char)); + buf = (unsigned char*)aCallocA(RFIFOW(fd,2) + 4, sizeof(char)); //printf("clif_parse_GlobalMessage: message: '%s'.\n", RFIFOP(fd,4)); - if (strncmp(RFIFOP(fd,4), sd->status.name, strlen(sd->status.name)) != 0) { + if (strncmp((char*)RFIFOP(fd,4), sd->status.name, strlen(sd->status.name)) != 0) { printf("Hack on global message: character '%s' (account: %d), use an other name to send a (normal) message.\n", sd->status.name, sd->status.account_id); // information is sended to all online GM - sprintf(message, "Hack on global message (normal message): character '%s' (account: %d) uses an other name.", sd->status.name, sd->status.account_id); - intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message, strlen(message) + 1); - if (strlen(RFIFOP(fd,4)) == 0) + sprintf(message, "Hack on global message (normal message): character '%s' (account: %d) uses another name.", sd->status.name, sd->status.account_id); + intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message); + if (strlen((char*)RFIFOP(fd,4)) == 0) strcpy(message, " This player sends a void name and a void message."); else sprintf(message, " This player sends (name:message): '%s'.", RFIFOP(fd,4)); - intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message, strlen(message) + 1); + intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message); // message about the ban if (battle_config.ban_spoof_namer > 0) sprintf(message, " This player has been banned for %d minute(s).", battle_config.ban_spoof_namer); else sprintf(message, " This player hasn't been banned (Ban option is disabled)."); - intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message, strlen(message) + 1); + intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message); // if we ban people if (battle_config.ban_spoof_namer > 0) { chrif_char_ask_name(-1, sd->status.name, 2, 0, 0, 0, 0, battle_config.ban_spoof_namer, 0); // type: 2 - ban (year, month, day, hour, minute, second) clif_setwaitclose(fd); // forced to disconnect because of the hack + + if(message) aFree(message); + if(buf) aFree(buf); + + return; } // but for the hacker, we display on his screen (he see/look no difference). } else { @@ -7696,8 +8006,37 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) { // S 008c < WFIFOW(fd,0) = 0x8e; WFIFOSET(fd, WFIFOW(fd,2)); - if(message) free(message); - if(buf) free(buf); +#ifdef PCRE_SUPPORT + map_foreachinarea(npc_chat_sub, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_NPC, RFIFOP(fd,4), strlen(RFIFOP(fd,4)), &sd->bl); +#endif + + // Celest + if (pc_calc_base_job2 (sd->status.class_) == 23 ) { + int next = pc_nextbaseexp(sd)>0 ? pc_nextbaseexp(sd) : sd->status.base_exp; + if (next > 0 && (sd->status.base_exp*100/next)%10 == 0) { + estr_lower((char*)RFIFOP(fd,4)); + if (sd->state.snovice_flag == 0 && strstr((char*)RFIFOP(fd,4), msg_txt(504))) + sd->state.snovice_flag = 1; + else if (sd->state.snovice_flag == 1) { + sprintf(message, msg_txt(505), sd->status.name); + estr_lower(message); + if (strstr((char*)RFIFOP(fd,4), message)) + sd->state.snovice_flag = 2; + } + else if (sd->state.snovice_flag == 2 && strstr((char*)RFIFOP(fd,4), msg_txt(506))) + sd->state.snovice_flag = 3; + else if (sd->state.snovice_flag == 3) { + int i; + status_change_start(&sd->bl,SkillStatusChangeTable[MO_EXPLOSIONSPIRITS],1,0,0,0,skill_get_time(MO_EXPLOSIONSPIRITS,1),0 ); + for(i=0;i<5;i++) + pc_addspiritball(sd,skill_get_time(MO_CALLSPIRITS,1),5); + sd->state.snovice_flag = 0; + } + } + } + + if(message) aFree(message); + if(buf) aFree(buf); return; } @@ -7714,7 +8053,7 @@ int clif_message(struct block_list *bl, char* msg) WBUFL(buf, 4) = bl->id; memcpy(WBUFP(buf, 8), msg, msg_len); - clif_send(buf, WBUFW(buf,2), bl, AREA); + clif_send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); // by Gengar return 0; } @@ -7725,17 +8064,20 @@ int clif_message(struct block_list *bl, char* msg) */ void clif_parse_MapMove(int fd, struct map_session_data *sd) { // /m /mapmove (as @rura GM command) - char output[100]; + char output[30]; // 17+4+4=26, 30 max. char map_name[17]; nullpo_retv(sd); - memset(output, '\0', sizeof(output)); - memset(map_name, '\0', sizeof(map_name)); +// not needed at all as far as sprintf is used // [Ilpalazzo-sama] +// memset(output, '\0', sizeof(output)); +// not needed -- map_name[16]='\0'; will do +// memset(map_name, '\0', sizeof(map_name)); if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) && (pc_isGM(sd) >= get_atcommand_level(AtCommand_MapMove))) { memcpy(map_name, RFIFOP(fd,2), 16); + map_name[16]='\0'; sprintf(output, "%s %d %d", map_name, RFIFOW(fd,18), RFIFOW(fd,20)); atcommand_rura(fd, sd, "@rura", output); } @@ -7747,58 +8089,89 @@ void clif_parse_MapMove(int fd, struct map_session_data *sd) { * *------------------------------------------ */ -void clif_parse_ChangeDir(int fd, struct map_session_data *sd) { +void clif_changed_dir(struct block_list *bl) { unsigned char buf[64]; + struct map_session_data *sd = NULL; + + if (bl->type == BL_PC) + nullpo_retv (sd=(struct map_session_data *)bl); + + WBUFW(buf,0) = 0x9c; + WBUFL(buf,2) = bl->id; + if (sd) + WBUFW(buf,6) = sd->head_dir; + WBUFB(buf,8) = status_get_dir(bl); + if (sd && sd->disguise > 23 && sd->disguise < 4001) // mob disguises [Valaris] + clif_send(buf, packet_len_table[0x9c], &sd->bl, AREA); + else + clif_send(buf, packet_len_table[0x9c], bl, AREA_WOS); + + return; +} + +/*========================================== + * + *------------------------------------------ + */ +void clif_parse_ChangeDir(int fd, struct map_session_data *sd) { short headdir, dir; nullpo_retv(sd); - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 7: - headdir = RFIFOW(fd,5); - dir = RFIFOB(fd,12); - break; - case 8: - headdir = RFIFOW(fd,5); - dir = RFIFOB(fd,12); - break; - case 9: - headdir = RFIFOW(fd,7); - dir = RFIFOB(fd,11); - break; - case 10: - headdir = RFIFOW(fd,4); - dir = RFIFOB(fd,9); - break; - case 11: - headdir = RFIFOW(fd,8); - dir = RFIFOB(fd,17); - break; - case 12: - headdir = RFIFOW(fd,5); - dir = RFIFOB(fd,12); - break; - case 13: - headdir = RFIFOW(fd,6); - dir = RFIFOB(fd,14); - break; - default: // old version by default (and packet version 6) - headdir = RFIFOW(fd,2); - dir = RFIFOB(fd,4); - break; + if (USE_PACKET_DB(sd)) { + headdir = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]); + dir = RFIFOB(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 7: + headdir = RFIFOW(fd,5); + dir = RFIFOB(fd,12); + break; + case 8: + headdir = RFIFOW(fd,5); + dir = RFIFOB(fd,12); + break; + case 9: + headdir = RFIFOW(fd,7); + dir = RFIFOB(fd,11); + break; + case 10: + headdir = RFIFOW(fd,4); + dir = RFIFOB(fd,9); + break; + case 11: + headdir = RFIFOW(fd,8); + dir = RFIFOB(fd,17); + break; + case 12: + headdir = RFIFOW(fd,5); + dir = RFIFOB(fd,12); + break; + case 13: + case 14: + headdir = RFIFOW(fd,6); + dir = RFIFOB(fd,14); + break; + case 15: + headdir = RFIFOW(fd,3); + dir = RFIFOB(fd,7); + break; + case 16: + headdir = RFIFOW(fd,12); + dir = RFIFOB(fd,22); + break; + + default: // old version by default (and packet version 6) + headdir = RFIFOW(fd,2); + dir = RFIFOB(fd,4); + break; + } } pc_setdir(sd, dir, headdir); - WBUFW(buf,0) = 0x9c; - WBUFL(buf,2) = sd->bl.id; - WBUFW(buf,6) = headdir; - WBUFB(buf,8) = dir; - if (sd->disguise > 23 && sd->disguise < 4001) // mob disguises [Valaris] - clif_send(buf, packet_len_table[0x9c], &sd->bl, AREA); - else - clif_send(buf, packet_len_table[0x9c], &sd->bl, AREA_WOS); - + clif_changed_dir(&sd->bl); + return; } /*========================================== @@ -7811,10 +8184,20 @@ void clif_parse_Emotion(int fd, struct map_session_data *sd) { nullpo_retv(sd); if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, NV_BASIC) >= 2) { + if (RFIFOB(fd,2) == 34) {// prevent use of the mute emote [Valaris] + clif_skill_fail(sd, 1, 0, 1); + return; + } + // fix flood of emotion icon (ro-proxy): flood only the hacker player + if (sd->emotionlasttime >= time(NULL)) { + sd->emotionlasttime = time(NULL) + 2; // not more than 1 every 2 seconds (normal client is every 3-4 seconds) + clif_skill_fail(sd, 1, 0, 1); + return; + } + sd->emotionlasttime = time(NULL) + 2; // not more than 1 every 2 seconds (normal client is every 3-4 seconds) + WBUFW(buf,0) = 0xc0; WBUFL(buf,2) = sd->bl.id; - if(RFIFOB(fd,2)==34) // prevent use of the mute emote [Valaris] - return; WBUFB(buf,6) = RFIFOB(fd,2); clif_send(buf, packet_len_table[0xc0], &sd->bl, AREA); } else @@ -7848,7 +8231,8 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) { } if (sd->npc_id != 0 || sd->opt1 > 0 || sd->status.option & 2 || (sd->sc_data && - (sd->sc_data[SC_AUTOCOUNTER].timer != -1 || //ƒI[ƒgƒJƒEƒ“ƒ^[ + (sd->sc_data[SC_TRICKDEAD].timer != -1 || + sd->sc_data[SC_AUTOCOUNTER].timer != -1 || //ƒI[ƒgƒJƒEƒ“ƒ^[ sd->sc_data[SC_BLADESTOP].timer != -1 || //”’nŽæ‚è sd->sc_data[SC_DANCING].timer != -1))) //ƒ_ƒ“ƒX’† return; @@ -7858,35 +8242,50 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) { pc_stop_walking(sd, 0); pc_stopattack(sd); - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 8: - target_id = RFIFOL(fd,3); - action_type = RFIFOB(fd,8); - break; - case 9: - target_id = RFIFOL(fd,7); - action_type = RFIFOB(fd,17); - break; - case 10: - target_id = RFIFOL(fd,9); - action_type = RFIFOB(fd,22); - break; - case 11: - target_id = RFIFOL(fd,3); - action_type = RFIFOB(fd,8); - break; - case 12: - target_id = RFIFOL(fd,3); - action_type = RFIFOB(fd,8); - break; - case 13: - target_id = RFIFOL(fd,4); - action_type = RFIFOB(fd,14); - break; - default: // old version by default (and packet version 6 and 7) - target_id = RFIFOL(fd,2); - action_type = RFIFOB(fd,6); - break; + if (USE_PACKET_DB(sd)) { + target_id = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]); + action_type = RFIFOB(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 8: + target_id = RFIFOL(fd,3); + action_type = RFIFOB(fd,8); + break; + case 9: + target_id = RFIFOL(fd,7); + action_type = RFIFOB(fd,17); + break; + case 10: + target_id = RFIFOL(fd,9); + action_type = RFIFOB(fd,22); + break; + case 11: + target_id = RFIFOL(fd,3); + action_type = RFIFOB(fd,8); + break; + case 12: + target_id = RFIFOL(fd,3); + action_type = RFIFOB(fd,8); + break; + case 13: + case 14: + target_id = RFIFOL(fd,4); + action_type = RFIFOB(fd,14); + break; + case 15: + target_id = RFIFOL(fd,6); + action_type = RFIFOB(fd,17); + break; + case 16: + target_id = RFIFOL(fd,9); + action_type = RFIFOB(fd,19); + break; + + default: // old version by default (and packet version 6 and 7) + target_id = RFIFOL(fd,2); + action_type = RFIFOB(fd,6); + break; + } } switch(action_type) { @@ -7911,15 +8310,15 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) { case 0x02: // sitdown if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, NV_BASIC) >= 3) { pc_stop_walking(sd, 1); - skill_gangsterparadise(sd, 1); // ƒMƒƒƒ“ƒOƒXƒ^[ƒpƒ‰ƒ_ƒCƒXÝ’è pc_setsit(sd); + skill_gangsterparadise(sd, 1); // ƒMƒƒƒ“ƒOƒXƒ^[ƒpƒ‰ƒ_ƒCƒXÝ’è fixed Valaris clif_sitting(sd); } else clif_skill_fail(sd, 1, 0, 2); break; case 0x03: // standup - skill_gangsterparadise(sd, 0); // ƒMƒƒƒ“ƒOƒXƒ^[ƒpƒ‰ƒ_ƒCƒX‰ðœ pc_setstand(sd); + skill_gangsterparadise(sd, 0); // ƒMƒƒƒ“ƒOƒXƒ^[ƒpƒ‰ƒ_ƒCƒX‰ðœ fixed Valaris WBUFW(buf, 0) = 0x8a; WBUFL(buf, 2) = sd->bl.id; WBUFB(buf,26) = 3; @@ -7942,6 +8341,9 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) { pc_setrestartvalue(sd, 3); pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, 2); } + // in case the player's status somehow wasn't updated yet [Celest] + else if (sd->status.hp <= 0) + pc_setdead(sd); break; case 0x01: if(!pc_isdead(sd) && (sd->opt1 || (sd->opt2 && !(night_flag == 1 && sd->opt2 == STATE_BLIND)))) @@ -7971,32 +8373,32 @@ void clif_parse_Wis(int fd, struct map_session_data *sd) { // S 0096 <len>.w <ni //printf("clif_parse_Wis: message: '%s'.\n", RFIFOP(fd,28)); - gm_command = (char*)aCalloc(strlen(RFIFOP(fd,28)) + 28, sizeof(char)); // 24+3+(RFIFOW(fd,2)-28)+1 or 24+3+(strlen(RFIFOP(fd,28))+1 (size can be wrong with hacker) + gm_command = (char*)aCallocA(strlen((const char*)RFIFOP(fd,28)) + 28, sizeof(char)); // 24+3+(RFIFOW(fd,2)-28)+1 or 24+3+(strlen(RFIFOP(fd,28))+1 (size can be wrong with hacker) sprintf(gm_command, "%s : %s", sd->status.name, RFIFOP(fd,28)); if ((is_charcommand(fd, sd, gm_command, 0) != CharCommand_None) || (is_atcommand(fd, sd, gm_command, 0) != AtCommand_None) || - (sd && sd->sc_data && + (sd && sd->sc_data && (sd->sc_data[SC_BERSERK].timer!=-1 || //ƒo[ƒT[ƒNŽž‚͉ï˜b‚à•s‰Â sd->sc_data[SC_NOCHAT].timer != -1))) //ƒ`ƒƒƒbƒg‹ÖŽ~ { - if(gm_command) free(gm_command); + if(gm_command) aFree(gm_command); return; } - if(gm_command) free(gm_command); + if(gm_command) aFree(gm_command); // searching destination character - dstsd = map_nick2sd(RFIFOP(fd,4)); + dstsd = map_nick2sd((char*)RFIFOP(fd,4)); // player is not on this map-server if (dstsd == NULL || // At this point, don't send wisp/page if it's not exactly the same name, because (example) // if there are 'Test' player on an other map-server and 'test' player on this map-server, // and if we ask for 'Test', we must not contact 'test' player // so, we send information to inter-server, which is the only one which decide (and copy correct name). - strcmp(dstsd->status.name, RFIFOP(fd,4)) != 0) // not exactly same name + strcmp(dstsd->status.name, (const char*)RFIFOP(fd,4)) != 0) // not exactly same name // send message to inter-server - intif_wis_message(sd, RFIFOP(fd,4), RFIFOP(fd,28), RFIFOW(fd,2)-28); + intif_wis_message(sd, (char*)RFIFOP(fd,4), (char*)RFIFOP(fd,28), RFIFOW(fd,2)-28); // player is on this map-server else { // if you send to your self, don't send anything to others @@ -8015,7 +8417,7 @@ void clif_parse_Wis(int fd, struct map_session_data *sd) { // S 0096 <len>.w <ni } // if source player not found in ignore list if (i == MAX_IGNORE_LIST) { - clif_wis_message(dstsd->fd, sd->status.name, RFIFOP(fd,28), RFIFOW(fd,2) - 28); + clif_wis_message(dstsd->fd, sd->status.name, (char*)RFIFOP(fd,28), RFIFOW(fd,2) - 28); clif_wis_end(fd, 0); // type: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target } } @@ -8035,7 +8437,7 @@ void clif_parse_GMmessage(int fd, struct map_session_data *sd) { if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) && (pc_isGM(sd) >= get_atcommand_level(AtCommand_Broadcast))) - intif_GMmessage(RFIFOP(fd,4), RFIFOW(fd,2)-4, 0); + intif_GMmessage((char*)RFIFOP(fd,4), RFIFOW(fd,2)-4, 0); } /*========================================== @@ -8048,31 +8450,42 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd) { nullpo_retv(sd); - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 7: - map_object_id = RFIFOL(fd,6); - break; - case 8: - map_object_id = RFIFOL(fd,6); - break; - case 9: - map_object_id = RFIFOL(fd,9); - break; - case 10: - map_object_id = RFIFOL(fd,7); - break; - case 11: - map_object_id = RFIFOL(fd,10); - break; - case 12: - map_object_id = RFIFOL(fd,6); - break; - case 13: - map_object_id = RFIFOL(fd,5); - break; - default: // old version by default (and packet version 6) - map_object_id = RFIFOL(fd,2); - break; + if (USE_PACKET_DB(sd)) { + map_object_id = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 7: + map_object_id = RFIFOL(fd,6); + break; + case 8: + map_object_id = RFIFOL(fd,6); + break; + case 9: + map_object_id = RFIFOL(fd,9); + break; + case 10: + map_object_id = RFIFOL(fd,7); + break; + case 11: + map_object_id = RFIFOL(fd,10); + break; + case 12: + map_object_id = RFIFOL(fd,6); + break; + case 13: + case 14: + map_object_id = RFIFOL(fd,5); + break; + case 15: + map_object_id = RFIFOL(fd,3); + break; + case 16: + map_object_id = RFIFOL(fd,5); + break; + default: // old version by default (and packet version 6) + map_object_id = RFIFOL(fd,2); + break; + } } fitem = (struct flooritem_data*)map_id2bl(map_object_id); @@ -8113,35 +8526,49 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd) { sd->sc_data[SC_BERSERK].timer != -1)) ) //ƒo[ƒT[ƒN return; - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 8: - item_index = RFIFOW(fd,5) - 2; - item_amount = RFIFOW(fd,12); - break; - case 9: - item_index = RFIFOW(fd,8) - 2; - item_amount = RFIFOW(fd,15); - break; - case 10: - item_index = RFIFOW(fd,6) - 2; - item_amount = RFIFOW(fd,15); - break; - case 11: - item_index = RFIFOW(fd,12) - 2; - item_amount = RFIFOW(fd,17); - break; - case 12: - item_index = RFIFOW(fd,5) - 2; - item_amount = RFIFOW(fd,12); - break; - case 13: - item_index = RFIFOW(fd,6) - 2; - item_amount = RFIFOW(fd,10); - break; - default: // old version by default (+ packet version 6 and 7) - item_index = RFIFOW(fd,2) - 2; - item_amount = RFIFOW(fd,4); - break; + if (USE_PACKET_DB(sd)) { + item_index = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0])-2; + item_amount = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 8: + item_index = RFIFOW(fd,5) - 2; + item_amount = RFIFOW(fd,12); + break; + case 9: + item_index = RFIFOW(fd,8) - 2; + item_amount = RFIFOW(fd,15); + break; + case 10: + item_index = RFIFOW(fd,6) - 2; + item_amount = RFIFOW(fd,15); + break; + case 11: + item_index = RFIFOW(fd,12) - 2; + item_amount = RFIFOW(fd,17); + break; + case 12: + item_index = RFIFOW(fd,5) - 2; + item_amount = RFIFOW(fd,12); + break; + case 13: + case 14: + item_index = RFIFOW(fd,6) - 2; + item_amount = RFIFOW(fd,10); + break; + case 15: + item_index = RFIFOW(fd,4) - 2; + item_amount = RFIFOW(fd,10); + break; + case 16: + item_index = RFIFOW(fd,15) - 2; + item_amount = RFIFOW(fd,18); + break; + default: // old version by default (+ packet version 6 and 7) + item_index = RFIFOW(fd,2) - 2; + item_amount = RFIFOW(fd,4); + break; + } } pc_dropitem(sd, item_index, item_amount); @@ -8158,7 +8585,7 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd) { clif_clearchar_area(&sd->bl, 1); return; } - if (sd->npc_id!=0 || sd->vender_id != 0 || sd->opt1 > 0 || + if (sd->npc_id!=0 || sd->vender_id != 0 || (sd->opt1 > 0 && sd->opt1 != 6) || (sd->sc_data && (sd->sc_data[SC_TRICKDEAD].timer != -1 || //Ž€‚ñ‚¾‚Ó‚è sd->sc_data[SC_BLADESTOP].timer != -1 || //”’nŽæ‚è sd->sc_data[SC_BERSERK].timer!=-1 || //ƒo[ƒT[ƒN @@ -8168,34 +8595,45 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd) { if (sd->invincible_timer != -1) pc_delinvincibletimer(sd); - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 6: - pc_useitem(sd,RFIFOW(fd,5)-2); - break; - case 7: - pc_useitem(sd,RFIFOW(fd,6)-2); - break; - case 8: - pc_useitem(sd,RFIFOW(fd,6)-2); - break; - case 9: - pc_useitem(sd,RFIFOW(fd,9)-2); - break; - case 10: - pc_useitem(sd,RFIFOW(fd,7)-2); - break; - case 11: - pc_useitem(sd,RFIFOW(fd,10)-2); - break; - case 12: - pc_useitem(sd,RFIFOW(fd,6)-2); - break; - case 13: - pc_useitem(sd,RFIFOW(fd,5)-2); - break; - default: // old version by default - pc_useitem(sd,RFIFOW(fd,2)-2); - break; + if (USE_PACKET_DB(sd)) { + pc_useitem(sd,RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0])-2); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 6: + pc_useitem(sd,RFIFOW(fd,5)-2); + break; + case 7: + pc_useitem(sd,RFIFOW(fd,6)-2); + break; + case 8: + pc_useitem(sd,RFIFOW(fd,6)-2); + break; + case 9: + pc_useitem(sd,RFIFOW(fd,9)-2); + break; + case 10: + pc_useitem(sd,RFIFOW(fd,7)-2); + break; + case 11: + pc_useitem(sd,RFIFOW(fd,10)-2); + break; + case 12: + pc_useitem(sd,RFIFOW(fd,6)-2); + break; + case 13: + case 14: + pc_useitem(sd,RFIFOW(fd,5)-2); + break; + case 15: + pc_useitem(sd,RFIFOW(fd,3)-2); + break; + case 16: + pc_useitem(sd,RFIFOW(fd,5)-2); + break; + default: // old version by default + pc_useitem(sd,RFIFOW(fd,2)-2); + break; + } } } @@ -8246,17 +8684,18 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd) clif_clearchar_area(&sd->bl,1); return; } + if(sd->npc_id!=0 || sd->vender_id != 0 || sd->opt1 > 0) + return; index = RFIFOW(fd,2)-2; - if(sd->status.inventory[index].attribute == 1 && sd->sc_data && sd->sc_data[SC_BROKNWEAPON].timer!=-1) - skill_status_change_end(&sd->bl,SC_BROKNWEAPON,-1); + + /*if(sd->status.inventory[index].attribute == 1 && sd->sc_data && sd->sc_data[SC_BROKNWEAPON].timer!=-1) + status_change_end(&sd->bl,SC_BROKNWEAPON,-1); if(sd->status.inventory[index].attribute == 1 && sd->sc_data && sd->sc_data[SC_BROKNARMOR].timer!=-1) - skill_status_change_end(&sd->bl,SC_BROKNARMOR,-1); - if(sd->sc_data && ( sd->sc_data[SC_BLADESTOP].timer!=-1 || sd->sc_data[SC_BERSERK].timer!=-1 )) - return; + status_change_end(&sd->bl,SC_BROKNARMOR,-1); + if(sd->sc_count && ( sd->sc_data[SC_BLADESTOP].timer!=-1 || sd->sc_data[SC_BERSERK].timer!=-1 )) + return;*/ - if(sd->npc_id!=0 || sd->vender_id != 0 || sd->opt1 > 0) - return; - pc_unequipitem(sd,index,0,BF_NORMAL); + pc_unequipitem(sd,index,1); } /*========================================== @@ -8330,7 +8769,7 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) void clif_parse_CreateChatRoom(int fd,struct map_session_data *sd) { if(battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_BASIC) >= 4){ - chat_createchat(sd,RFIFOW(fd,4),RFIFOB(fd,6),RFIFOP(fd,7),RFIFOP(fd,15),RFIFOW(fd,2)-15); + chat_createchat(sd,RFIFOW(fd,4),RFIFOB(fd,6),(char*)RFIFOP(fd,7),(char*)RFIFOP(fd,15),RFIFOW(fd,2)-15); } else clif_skill_fail(sd,1,0,3); } @@ -8341,7 +8780,7 @@ void clif_parse_CreateChatRoom(int fd,struct map_session_data *sd) */ void clif_parse_ChatAddMember(int fd,struct map_session_data *sd) { - chat_joinchat(sd,RFIFOL(fd,2),RFIFOP(fd,6)); + chat_joinchat(sd,RFIFOL(fd,2),(char*)RFIFOP(fd,6)); } /*========================================== @@ -8350,7 +8789,7 @@ void clif_parse_ChatAddMember(int fd,struct map_session_data *sd) */ void clif_parse_ChatRoomStatusChange(int fd,struct map_session_data *sd) { - chat_changechatstatus(sd,RFIFOW(fd,4),RFIFOB(fd,6),RFIFOP(fd,7),RFIFOP(fd,15),RFIFOW(fd,2)-15); + chat_changechatstatus(sd,RFIFOW(fd,4),RFIFOB(fd,6),(char*)RFIFOP(fd,7),(char*)RFIFOP(fd,15),RFIFOW(fd,2)-15); } /*========================================== @@ -8359,7 +8798,7 @@ void clif_parse_ChatRoomStatusChange(int fd,struct map_session_data *sd) */ void clif_parse_ChangeChatOwner(int fd,struct map_session_data *sd) { - chat_changechatowner(sd,RFIFOP(fd,6)); + chat_changechatowner(sd,(char*)RFIFOP(fd,6)); } /*========================================== @@ -8368,7 +8807,7 @@ void clif_parse_ChangeChatOwner(int fd,struct map_session_data *sd) */ void clif_parse_KickFromChat(int fd,struct map_session_data *sd) { - chat_kickchat(sd,RFIFOP(fd,2)); + chat_kickchat(sd,(char*)RFIFOP(fd,2)); } /*========================================== @@ -8429,7 +8868,7 @@ void clif_parse_TradeOk(int fd,struct map_session_data *sd) * ŽæˆøƒLƒƒƒ“ƒZƒ‹ *------------------------------------------ */ -void clif_parse_TradeCansel(int fd,struct map_session_data *sd) +void clif_parse_TradeCancel(int fd,struct map_session_data *sd) { trade_tradecancel(sd); } @@ -8483,17 +8922,17 @@ void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd) void clif_parse_RemoveOption(int fd,struct map_session_data *sd) { if(pc_isriding(sd)) { // jobchange when removing peco [Valaris] - if(sd->status.class==13) - sd->status.class=sd->view_class=7; + if(sd->status.class_==13) + sd->status.class_=sd->view_class=7; - if(sd->status.class==21) - sd->status.class=sd->view_class=14; + if(sd->status.class_==21) + sd->status.class_=sd->view_class=14; - if(sd->status.class==4014) - sd->status.class=sd->view_class=4008; + if(sd->status.class_==4014) + sd->status.class_=sd->view_class=4008; - if(sd->status.class==4022) - sd->status.class=sd->view_class=4015; + if(sd->status.class_==4022) + sd->status.class_=sd->view_class=4015; } pc_setoption(sd,0); @@ -8539,52 +8978,69 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) { if (sd->chatID || sd->npc_id != 0 || sd->vender_id != 0) return; - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 6: - skilllv = RFIFOW(fd,4); - skillnum = RFIFOW(fd,9); - target_id = RFIFOL(fd,11); - break; - case 7: - skilllv = RFIFOW(fd,7); - skillnum = RFIFOW(fd,9); - target_id = RFIFOL(fd,15); - break; - case 8: - skilllv = RFIFOW(fd,7); - skillnum = RFIFOW(fd,12); - target_id = RFIFOL(fd,16); - break; - case 9: - skilllv = RFIFOW(fd,11); - skillnum = RFIFOW(fd,18); - target_id = RFIFOL(fd,22); - break; - case 10: - skilllv = RFIFOW(fd,9); - skillnum = RFIFOW(fd,15); - target_id = RFIFOL(fd,18); - break; - case 11: - skilllv = RFIFOW(fd,4); - skillnum = RFIFOW(fd,7); - target_id = RFIFOL(fd,10); - break; - case 12: - skilllv = RFIFOW(fd,7); - skillnum = RFIFOW(fd,12); - target_id = RFIFOL(fd,16); - break; - case 13: - skilllv = RFIFOW(fd,4); - skillnum = RFIFOW(fd,10); - target_id = RFIFOL(fd,22); - break; - default: // old version by default - skilllv = RFIFOW(fd,2); - skillnum = RFIFOW(fd,4); - target_id = RFIFOL(fd,6); - break; + if (USE_PACKET_DB(sd)) { + skilllv = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]); + skillnum = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]); + target_id = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[2]); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 6: + skilllv = RFIFOW(fd,4); + skillnum = RFIFOW(fd,9); + target_id = RFIFOL(fd,11); + break; + case 7: + skilllv = RFIFOW(fd,7); + skillnum = RFIFOW(fd,9); + target_id = RFIFOL(fd,15); + break; + case 8: + skilllv = RFIFOW(fd,7); + skillnum = RFIFOW(fd,12); + target_id = RFIFOL(fd,16); + break; + case 9: + skilllv = RFIFOW(fd,11); + skillnum = RFIFOW(fd,18); + target_id = RFIFOL(fd,22); + break; + case 10: + skilllv = RFIFOW(fd,9); + skillnum = RFIFOW(fd,15); + target_id = RFIFOL(fd,18); + break; + case 11: + skilllv = RFIFOW(fd,4); + skillnum = RFIFOW(fd,7); + target_id = RFIFOL(fd,10); + break; + case 12: + skilllv = RFIFOW(fd,7); + skillnum = RFIFOW(fd,12); + target_id = RFIFOL(fd,16); + break; + case 13: + case 14: + skilllv = RFIFOW(fd,4); + skillnum = RFIFOW(fd,10); + target_id = RFIFOL(fd,22); + break; + case 15: + skilllv = RFIFOW(fd,8); + skillnum = RFIFOW(fd,12); + target_id = RFIFOL(fd,18); + break; + case 16: + skilllv = RFIFOW(fd,8); + skillnum = RFIFOW(fd,16); + target_id = RFIFOL(fd,22); + break; + default: // old version by default + skilllv = RFIFOW(fd,2); + skillnum = RFIFOW(fd,4); + target_id = RFIFOL(fd,6); + break; + } } if (skillnotok(skillnum, sd)) @@ -8593,12 +9049,20 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) { if (sd->skilltimer != -1) { if (skillnum != SA_CASTCANCEL) return; - } else if (DIFF_TICK(tick, sd->canact_tick) < 0) { + } else if (DIFF_TICK(tick, sd->canact_tick) < 0 && + // allow monk combos to ignore this delay [celest] + !(sd->sc_count && sd->sc_data[SC_COMBO].timer!=-1 && + (skillnum == MO_EXTREMITYFIST || + skillnum == MO_CHAINCOMBO || + skillnum == MO_COMBOFINISH || + skillnum == CH_PALMSTRIKE || + skillnum == CH_TIGERFIST || + skillnum == CH_CHAINCRUSH))) { clif_skill_fail(sd, skillnum, 4, 0); return; } - if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) || + if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) || sd->sc_data[SC_BERSERK].timer != -1 || sd->sc_data[SC_NOCHAT].timer != -1 || sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class == 22) return; @@ -8621,6 +9085,20 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) { return; } } + } else if (skillnum == CH_TIGERFIST) { + if (sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH) { + if (!sd->state.skill_flag ) { + sd->state.skill_flag = 1; + if (!sd->attacktarget) { + clif_skillinfo(sd, CH_TIGERFIST, 1, -2); + return; + } else + target_id = sd->attacktarget; + } else if (sd->bl.id == target_id) { + clif_skillinfo(sd, CH_TIGERFIST, 1, -2); + return; + } + } } if ((lv = pc_checkskill(sd, skillnum)) > 0) { if (skilllv > lv) @@ -8647,79 +9125,103 @@ void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) { if(sd->chatID) return; skillmoreinfo = -1; - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 6: - skilllv = RFIFOW(fd,4); - skillnum = RFIFOW(fd,9); - x = RFIFOW(fd,11); - y = RFIFOW(fd,13); - if (RFIFOW(fd,0) == 0x190) - skillmoreinfo = 15; - break; - case 7: - skilllv = RFIFOW(fd,7); - skillnum = RFIFOW(fd,9); - x = RFIFOW(fd,15); - y = RFIFOW(fd,17); - if (RFIFOW(fd,0) == 0x190) - skillmoreinfo = 19; - break; - case 8: - skilllv = RFIFOW(fd,3); - skillnum = RFIFOW(fd,6); - x = RFIFOW(fd,17); - y = RFIFOW(fd,21); - if (RFIFOW(fd,0) == 0x0a2) - skillmoreinfo = 23; - break; - case 9: - skilllv = RFIFOW(fd,5); - skillnum = RFIFOW(fd,15); - x = RFIFOW(fd,29); - y = RFIFOW(fd,38); - if (RFIFOW(fd,0) == 0x0a2) - skillmoreinfo = 40; - break; - case 10: - skilllv = RFIFOW(fd,10); - skillnum = RFIFOW(fd,14); - x = RFIFOW(fd,18); - y = RFIFOW(fd,23); - if (RFIFOW(fd,0) == 0x08c) - skillmoreinfo = 25; - break; - case 11: - skilllv = RFIFOW(fd,6); // 16? to check. - skillnum = RFIFOW(fd,20); - x = RFIFOW(fd,23); - y = RFIFOW(fd,27); - if (RFIFOW(fd,0) == 0x08c) - skillmoreinfo = 29; - break; - case 12: - skilllv = RFIFOW(fd,3); // 2? to check. - skillnum = RFIFOW(fd,6); - x = RFIFOW(fd,17); - y = RFIFOW(fd,21); - if (RFIFOW(fd,0) == 0x08c) - skillmoreinfo = 23; - break; - case 13: - skilllv = RFIFOW(fd,6); - skillnum = RFIFOW(fd,9); - x = RFIFOW(fd,23); - y = RFIFOW(fd,26); - if (RFIFOW(fd,0) == 0x08c) - skillmoreinfo = 28; - break; - default: // old version by default - skilllv = RFIFOW(fd,2); - skillnum = RFIFOW(fd,4); - x = RFIFOW(fd,6); - y = RFIFOW(fd,8); - if (RFIFOW(fd,0) == 0x190) - skillmoreinfo = 10; - break; + if (USE_PACKET_DB(sd)) { + skilllv = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]); + skillnum = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]); + x = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[2]); + y = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[3]); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 6: + skilllv = RFIFOW(fd,4); + skillnum = RFIFOW(fd,9); + x = RFIFOW(fd,11); + y = RFIFOW(fd,13); + if (RFIFOW(fd,0) == 0x190) + skillmoreinfo = 15; + break; + case 7: + skilllv = RFIFOW(fd,7); + skillnum = RFIFOW(fd,9); + x = RFIFOW(fd,15); + y = RFIFOW(fd,17); + if (RFIFOW(fd,0) == 0x190) + skillmoreinfo = 19; + break; + case 8: + skilllv = RFIFOW(fd,3); + skillnum = RFIFOW(fd,6); + x = RFIFOW(fd,17); + y = RFIFOW(fd,21); + if (RFIFOW(fd,0) == 0x0a2) + skillmoreinfo = 23; + break; + case 9: + skilllv = RFIFOW(fd,5); + skillnum = RFIFOW(fd,15); + x = RFIFOW(fd,29); + y = RFIFOW(fd,38); + if (RFIFOW(fd,0) == 0x0a2) + skillmoreinfo = 40; + break; + case 10: + skilllv = RFIFOW(fd,10); + skillnum = RFIFOW(fd,14); + x = RFIFOW(fd,18); + y = RFIFOW(fd,23); + if (RFIFOW(fd,0) == 0x08c) + skillmoreinfo = 25; + break; + case 11: + skilllv = RFIFOW(fd,6); // 16? to check. + skillnum = RFIFOW(fd,20); + x = RFIFOW(fd,23); + y = RFIFOW(fd,27); + if (RFIFOW(fd,0) == 0x08c) + skillmoreinfo = 29; + break; + case 12: + skilllv = RFIFOW(fd,3); // 2? to check. + skillnum = RFIFOW(fd,6); + x = RFIFOW(fd,17); + y = RFIFOW(fd,21); + if (RFIFOW(fd,0) == 0x08c) + skillmoreinfo = 23; + break; + case 13: + case 14: + skilllv = RFIFOW(fd,6); + skillnum = RFIFOW(fd,9); + x = RFIFOW(fd,23); + y = RFIFOW(fd,26); + if (RFIFOW(fd,0) == 0x08c) + skillmoreinfo = 28; + break; + case 15: + skilllv = RFIFOW(fd,4); + skillnum = RFIFOW(fd,9); + x = RFIFOW(fd,22); + y = RFIFOW(fd,28); + if (RFIFOW(fd,0) == 0x113) + skillmoreinfo = 30; + break; + case 16: + skilllv = RFIFOW(fd,9); + skillnum = RFIFOW(fd,18); + x = RFIFOW(fd,22); + y = RFIFOW(fd,32); + if (RFIFOW(fd,0) == 0x07e) + skillmoreinfo = 34; + break; + default: // old version by default + skilllv = RFIFOW(fd,2); + skillnum = RFIFOW(fd,4); + x = RFIFOW(fd,6); + y = RFIFOW(fd,8); + if (RFIFOW(fd,0) == 0x190) + skillmoreinfo = 10; + break; + } } if (skillnotok(skillnum, sd)) @@ -8735,12 +9237,20 @@ void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) { if (sd->skilltimer != -1) return; - else if (DIFF_TICK(tick, sd->canact_tick) < 0) { + else if (DIFF_TICK(tick, sd->canact_tick) < 0 && + // allow monk combos to ignore this delay [celest] + !(sd->sc_count && sd->sc_data[SC_COMBO].timer!=-1 && + (skillnum == MO_EXTREMITYFIST || + skillnum == MO_CHAINCOMBO || + skillnum == MO_COMBOFINISH || + skillnum == CH_PALMSTRIKE || + skillnum == CH_TIGERFIST || + skillnum == CH_CHAINCRUSH))) { clif_skill_fail(sd, skillnum, 4, 0); return; } - if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) || + if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) || sd->sc_data[SC_BERSERK].timer != -1 || sd->sc_data[SC_NOCHAT].timer != -1 || sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class == 22) return; @@ -8770,7 +9280,7 @@ void clif_parse_UseSkillMap(int fd,struct map_session_data *sd) if(sd->chatID) return; - if (sd->npc_id!=0 || sd->vender_id != 0 || (sd->sc_data && + if (sd->npc_id!=0 || sd->vender_id != 0 || (sd->sc_data && (sd->sc_data[SC_TRICKDEAD].timer != -1 || sd->sc_data[SC_BERSERK].timer!=-1 || sd->sc_data[SC_NOCHAT].timer!=-1 || @@ -8781,7 +9291,7 @@ void clif_parse_UseSkillMap(int fd,struct map_session_data *sd) if(sd->invincible_timer != -1) pc_delinvincibletimer(sd); - skill_castend_map(sd,RFIFOW(fd,2),RFIFOP(fd,4)); + skill_castend_map(sd,RFIFOW(fd,2),(char*)RFIFOP(fd,4)); } /*========================================== * ƒƒ‚—v‹ @@ -8854,7 +9364,7 @@ void clif_parse_NpcStringInput(int fd,struct map_session_data *sd) memcpy(sd->npc_str,RFIFOP(fd,8),sizeof(sd->npc_str)); sd->npc_str[sizeof(sd->npc_str)-1]=0; } else - strcpy(sd->npc_str,RFIFOP(fd,8)); + strcpy(sd->npc_str,(char*)RFIFOP(fd,8)); npc_scriptcont(sd,RFIFOL(fd,4)); } @@ -8918,28 +9428,39 @@ void clif_parse_InsertCard(int fd,struct map_session_data *sd) void clif_parse_SolveCharName(int fd, struct map_session_data *sd) { int char_id; - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 8: - char_id = RFIFOL(fd,8); - break; - case 9: - char_id = RFIFOL(fd,7); - break; - case 10: - char_id = RFIFOL(fd,10); - break; - case 11: - char_id = RFIFOL(fd,6); - break; - case 12: - char_id = RFIFOL(fd,8); - break; - case 13: - char_id = RFIFOL(fd,12); - break; - default: // old version by default (+ packet version 6 and 7) - char_id = RFIFOL(fd,2); - break; + if (USE_PACKET_DB(sd)) { + char_id = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 8: + char_id = RFIFOL(fd,8); + break; + case 9: + char_id = RFIFOL(fd,7); + break; + case 10: + char_id = RFIFOL(fd,10); + break; + case 11: + char_id = RFIFOL(fd,6); + break; + case 12: + char_id = RFIFOL(fd,8); + break; + case 13: + case 14: + char_id = RFIFOL(fd,12); + break; + case 15: + char_id = RFIFOL(fd,10); + break; + case 16: + char_id = RFIFOL(fd,7); + break; + default: // old version by default (+ packet version 6 and 7) + char_id = RFIFOL(fd,2); + break; + } } clif_solved_charname(sd, char_id); } @@ -8951,15 +9472,14 @@ void clif_parse_SolveCharName(int fd, struct map_session_data *sd) { void clif_parse_ResetChar(int fd, struct map_session_data *sd) { nullpo_retv(sd); - if (battle_config.atc_gmonly == 0 || pc_isGM(sd)) { + if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) && + pc_isGM(sd) >= get_atcommand_level(AtCommand_ResetState)) { switch(RFIFOW(fd,2)){ case 0: - if (pc_isGM(sd) >= get_atcommand_level(AtCommand_ResetState)) - pc_resetstate(sd); + pc_resetstate(sd); break; case 1: - if (pc_isGM(sd) >= get_atcommand_level(AtCommand_ResetState)) - pc_resetskill(sd); + pc_resetskill(sd); break; } } @@ -8970,7 +9490,7 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd) { *------------------------------------------ */ void clif_parse_LGMmessage(int fd, struct map_session_data *sd) { - unsigned char buf[64]; + unsigned char buf[512]; nullpo_retv(sd); @@ -8995,42 +9515,55 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) { if (sd->npc_id != 0 || sd->vender_id != 0) return; - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 8: - item_index = RFIFOW(fd,5) - 2; - item_amount = RFIFOL(fd,12); - break; - case 9: - item_index = RFIFOW(fd,5) - 2; - item_amount = RFIFOL(fd,19); - break; - case 10: - item_index = RFIFOW(fd,3) - 2; - item_amount = RFIFOL(fd,15); - break; - case 11: - item_index = RFIFOW(fd,6) - 2; - item_amount = RFIFOL(fd,21); - break; - case 12: - item_index = RFIFOW(fd,5) - 2; - item_amount = RFIFOL(fd,12); - break; - case 13: - item_index = RFIFOW(fd,6) - 2; - item_amount = RFIFOL(fd,9); - break; - default: // old version by default (+ packet version 6 and 7) - item_index = RFIFOW(fd,2) - 2; - item_amount = RFIFOL(fd,4); - break; + if (USE_PACKET_DB(sd)) { + item_index = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0])-2; + item_amount = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 8: + item_index = RFIFOW(fd,5) - 2; + item_amount = RFIFOL(fd,12); + break; + case 9: + item_index = RFIFOW(fd,5) - 2; + item_amount = RFIFOL(fd,19); + break; + case 10: + item_index = RFIFOW(fd,3) - 2; + item_amount = RFIFOL(fd,15); + break; + case 11: + item_index = RFIFOW(fd,6) - 2; + item_amount = RFIFOL(fd,21); + break; + case 12: + item_index = RFIFOW(fd,5) - 2; + item_amount = RFIFOL(fd,12); + break; + case 13: + case 14: + item_index = RFIFOW(fd,6) - 2; + item_amount = RFIFOL(fd,9); + break; + case 15: + item_index = RFIFOW(fd,4) - 2; + item_amount = RFIFOL(fd,10); + break; + case 16: + item_index = RFIFOW(fd,10) - 2; + item_amount = RFIFOL(fd,16); + break; + default: // old version by default (+ packet version 6 and 7) + item_index = RFIFOW(fd,2) - 2; + item_amount = RFIFOL(fd,4); + break; + } } if (item_index < 0 || item_index >= MAX_INVENTORY) return; if(itemdb_isdropable(sd->status.inventory[item_index].nameid) == 0) - return; if (sd->state.storage_flag) @@ -9048,35 +9581,49 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) { nullpo_retv(sd); - switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - case 8: - item_index = RFIFOW(fd,10) - 1; - item_amount = RFIFOL(fd,22); - break; - case 9: - item_index = RFIFOW(fd,11) - 1; - item_amount = RFIFOL(fd,22); - break; - case 10: - item_index = RFIFOW(fd,3) - 1; - item_amount = RFIFOL(fd,13); - break; - case 11: - item_index = RFIFOW(fd,4) - 1; - item_amount = RFIFOL(fd,8); - break; - case 12: - item_index = RFIFOW(fd,10) - 1; - item_amount = RFIFOL(fd,22); - break; - case 13: - item_index = RFIFOW(fd,12) - 1; - item_amount = RFIFOL(fd,18); - break; - default: // old version by default (+ packet version 6 and 7) - item_index = RFIFOW(fd,2) - 1; - item_amount = RFIFOL(fd,4); - break; + if (USE_PACKET_DB(sd)) { + item_index = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0])-1; + item_amount = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]); + } else { + switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + case 8: + item_index = RFIFOW(fd,10) - 1; + item_amount = RFIFOL(fd,22); + break; + case 9: + item_index = RFIFOW(fd,11) - 1; + item_amount = RFIFOL(fd,22); + break; + case 10: + item_index = RFIFOW(fd,3) - 1; + item_amount = RFIFOL(fd,13); + break; + case 11: + item_index = RFIFOW(fd,4) - 1; + item_amount = RFIFOL(fd,8); + break; + case 12: + item_index = RFIFOW(fd,10) - 1; + item_amount = RFIFOL(fd,22); + break; + case 13: + case 14: + item_index = RFIFOW(fd,12) - 1; + item_amount = RFIFOL(fd,18); + break; + case 15: + item_index = RFIFOW(fd,4) - 1; + item_amount = RFIFOL(fd,17); + break; + case 16: + item_index = RFIFOW(fd,11) - 1; + item_amount = RFIFOL(fd,17); + break; + default: // old version by default (+ packet version 6 and 7) + item_index = RFIFOW(fd,2) - 1; + item_amount = RFIFOL(fd,4); + break; + } } if (sd->npc_id != 0 || sd->vender_id != 0) @@ -9137,7 +9684,7 @@ void clif_parse_CloseKafra(int fd, struct map_session_data *sd) { */ void clif_parse_CreateParty(int fd, struct map_session_data *sd) { if (battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_BASIC) >= 7) { - party_create(sd,RFIFOP(fd,2)); + party_create(sd,(char*)RFIFOP(fd,2),0,0); } else clif_skill_fail(sd,1,0,4); } @@ -9148,9 +9695,9 @@ void clif_parse_CreateParty(int fd, struct map_session_data *sd) { */ void clif_parse_CreateParty2(int fd, struct map_session_data *sd) { if (battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_BASIC) >= 7){ - party_create(sd, RFIFOP(fd,2)); + party_create(sd,(char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOB(fd,27)); } else - clif_skill_fail(sd, 1, 0, 4); + clif_skill_fail(sd,1,0,4); } /*========================================== @@ -9187,7 +9734,7 @@ void clif_parse_LeaveParty(int fd, struct map_session_data *sd) { *------------------------------------------ */ void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) { - party_removemember(sd,RFIFOL(fd,2),RFIFOP(fd,6)); + party_removemember(sd,RFIFOL(fd,2),(char*)RFIFOP(fd,6)); } /*========================================== @@ -9204,16 +9751,15 @@ void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd) { */ void clif_parse_PartyMessage(int fd, struct map_session_data *sd) { nullpo_retv(sd); - if (is_charcommand(fd, sd, RFIFOP(fd,4), 0) != CharCommand_None) - return; - if (is_atcommand(fd, sd, RFIFOP(fd,4), 0) != AtCommand_None) - return; - if(sd->sc_data && + + if (is_charcommand(fd, sd, (char*)RFIFOP(fd,4), 0) != CharCommand_None || + is_atcommand(fd, sd, (char*)RFIFOP(fd,4), 0) != AtCommand_None || + (sd->sc_data && (sd->sc_data[SC_BERSERK].timer!=-1 || //ƒo[ƒT[ƒNŽž‚͉ï˜b‚à•s‰Â - sd->sc_data[SC_NOCHAT].timer!=-1)) //ƒ`ƒƒƒbƒg‹ÖŽ~ + sd->sc_data[SC_NOCHAT].timer!=-1))) //ƒ`ƒƒƒbƒg‹ÖŽ~ return; - party_send_message(sd, RFIFOP(fd,4), RFIFOW(fd,2)-4); + party_send_message(sd, (char*)RFIFOP(fd,4), RFIFOW(fd,2)-4); } /*========================================== @@ -9249,32 +9795,7 @@ void clif_parse_PurchaseReq(int fd, struct map_session_data *sd) { *------------------------------------------ */ void clif_parse_OpenVending(int fd,struct map_session_data *sd) { - vending_openvending(sd, RFIFOW(fd,2), RFIFOP(fd,4), RFIFOB(fd,84), RFIFOP(fd,85)); -} - -/*========================================== - * /monster /item rewriten by [Yor] - *------------------------------------------ - */ -void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) { - char monster_item_name[25]; - - nullpo_retv(sd); - - memset(monster_item_name, '\0', sizeof(monster_item_name)); - - if (battle_config.atc_gmonly == 0 || pc_isGM(sd)) { - memcpy(monster_item_name, RFIFOP(fd,2), 24); - - if (mobdb_searchname(monster_item_name) != 0) { - if (pc_isGM(sd) >= get_atcommand_level(AtCommand_Monster)) - atcommand_spawn(fd, sd, "@spawn", monster_item_name); // as @spawn - } else if (itemdb_searchname(monster_item_name) != NULL) { - if (pc_isGM(sd) >= get_atcommand_level(AtCommand_Item)) - atcommand_item(fd, sd, "@item", monster_item_name); // as @item - } - - } + vending_openvending(sd, RFIFOW(fd,2), (char*)RFIFOP(fd,4), RFIFOB(fd,84), RFIFOP(fd,85)); } /*========================================== @@ -9282,7 +9803,7 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) { *------------------------------------------ */ void clif_parse_CreateGuild(int fd,struct map_session_data *sd) { - guild_create(sd, RFIFOP(fd,6)); + guild_create(sd, (char*)RFIFOP(fd,6)); } /*========================================== @@ -9297,7 +9818,7 @@ void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd) { * ƒMƒ‹ƒhî•ñ—v‹ *------------------------------------------ */ -void clif_parse_GuildReqeustInfo(int fd, struct map_session_data *sd) { +void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) { switch(RFIFOL(fd,2)){ case 0: // ƒMƒ‹ƒhŠî–{î•ñA“¯–¿“G‘Îî•ñ clif_guild_basicinfo(sd); @@ -9332,7 +9853,7 @@ void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd) { int i; for(i = 4; i < RFIFOW(fd,2); i += 40 ){ - guild_change_position(sd, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), RFIFOP(fd,i+16)); + guild_change_position(sd, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), (char*)RFIFOP(fd,i+16)); } } @@ -9366,7 +9887,7 @@ void clif_parse_GuildRequestEmblem(int fd,struct map_session_data *sd) { *------------------------------------------ */ void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd) { - guild_change_emblem(sd,RFIFOW(fd,2)-4,RFIFOP(fd,4)); + guild_change_emblem(sd,RFIFOW(fd,2)-4,(char*)RFIFOP(fd,4)); } /*========================================== @@ -9374,7 +9895,7 @@ void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd) { *------------------------------------------ */ void clif_parse_GuildChangeNotice(int fd,struct map_session_data *sd) { - guild_change_notice(sd,RFIFOL(fd,2),RFIFOP(fd,6),RFIFOP(fd,66)); + guild_change_notice(sd,RFIFOL(fd,2),(char*)RFIFOP(fd,6),(char*)RFIFOP(fd,66)); } /*========================================== @@ -9398,7 +9919,7 @@ void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd) { *------------------------------------------ */ void clif_parse_GuildLeave(int fd,struct map_session_data *sd) { - guild_leave(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOP(fd,14)); + guild_leave(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); } /*========================================== @@ -9406,7 +9927,7 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd) { *------------------------------------------ */ void clif_parse_GuildExplusion(int fd,struct map_session_data *sd) { - guild_explusion(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOP(fd,14)); + guild_explusion(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); } /*========================================== @@ -9415,16 +9936,15 @@ void clif_parse_GuildExplusion(int fd,struct map_session_data *sd) { */ void clif_parse_GuildMessage(int fd,struct map_session_data *sd) { nullpo_retv(sd); - if (is_charcommand(fd, sd, RFIFOP(fd, 4), 0) != CharCommand_None) - return; - if (is_atcommand(fd, sd, RFIFOP(fd, 4), 0) != AtCommand_None) - return; - if(sd->sc_data && + + if (is_charcommand(fd, sd, (char*)RFIFOP(fd, 4), 0) != CharCommand_None || + is_atcommand(fd, sd, (char*)RFIFOP(fd, 4), 0) != AtCommand_None || + (sd->sc_data && (sd->sc_data[SC_BERSERK].timer!=-1 || //ƒo[ƒT[ƒNŽž‚͉ï˜b‚à•s‰Â - sd->sc_data[SC_NOCHAT].timer!=-1)) //ƒ`ƒƒƒbƒg‹ÖŽ~ + sd->sc_data[SC_NOCHAT].timer!=-1))) //ƒ`ƒƒƒbƒg‹ÖŽ~ return; - guild_send_message(sd, RFIFOP(fd,4), RFIFOW(fd,2)-4); + guild_send_message(sd, (char*)RFIFOP(fd,4), RFIFOW(fd,2)-4); } /*========================================== @@ -9464,7 +9984,7 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) { *------------------------------------------ */ void clif_parse_GuildBreak(int fd, struct map_session_data *sd) { - guild_break(sd,RFIFOP(fd,2)); + guild_break(sd,(char*)RFIFOP(fd,2)); } // pet @@ -9488,7 +10008,7 @@ void clif_parse_SendEmotion(int fd, struct map_session_data *sd) { } void clif_parse_ChangePetName(int fd, struct map_session_data *sd) { - pet_change_name(sd,RFIFOP(fd,2)); + pet_change_name(sd,(char*)RFIFOP(fd,2)); } // Kick (right click menu for GM "(name) force to quit") @@ -9559,6 +10079,31 @@ void clif_parse_Recall(int fd, struct map_session_data *sd) { // Added by RoVeRT return; } +/*========================================== + * /monster /item rewriten by [Yor] + *------------------------------------------ + */ +void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) { + char monster_item_name[25]; + + nullpo_retv(sd); + + memset(monster_item_name, '\0', sizeof(monster_item_name)); + + if (battle_config.atc_gmonly == 0 || pc_isGM(sd)) { + memcpy(monster_item_name, RFIFOP(fd,2), 24); + + if (mobdb_searchname(monster_item_name) != 0) { + if (pc_isGM(sd) >= get_atcommand_level(AtCommand_Monster)) + atcommand_spawn(fd, sd, "@spawn", monster_item_name); // as @spawn + } else if (itemdb_searchname(monster_item_name) != NULL) { + if (pc_isGM(sd) >= get_atcommand_level(AtCommand_Item)) + atcommand_item(fd, sd, "@item", monster_item_name); // as @item + } + + } +} + void clif_parse_GMHide(int fd, struct map_session_data *sd) { // Modified by [Yor] nullpo_retv(sd); @@ -9607,10 +10152,10 @@ void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) WFIFOSET(dstfd,packet_len_table[0x14b]); dstsd->status.manner -= limit; if(dstsd->status.manner < 0) - skill_status_change_start(bl,SC_NOCHAT,0,0,0,0,0,0); + status_change_start(bl,SC_NOCHAT,0,0,0,0,0,0); else{ dstsd->status.manner = 0; - skill_status_change_end(bl,SC_NOCHAT,-1); + status_change_end(bl,SC_NOCHAT,-1); } printf("name:%s type:%d limit:%d manner:%d\n",dstsd->status.name,type,limit,dstsd->status.manner); } @@ -9628,7 +10173,7 @@ void clif_parse_GMReqNoChatCount(int fd, struct map_session_data *sd) WFIFOW(fd,0) = 0x1e0; WFIFOL(fd,2) = tid; - sprintf(WFIFOP(fd,6),"%d",tid); + sprintf((char*)WFIFOP(fd,6),"%d",tid); // memcpy(WFIFOP(fd,6), "TESTNAME", 24); WFIFOSET(fd, packet_len_table[0x1e0]); @@ -9642,14 +10187,14 @@ void clif_parse_PMIgnore(int fd, struct map_session_data *sd) { // Rewritten by memset(output, '\0', sizeof(output)); - nick = RFIFOP(fd,2); // speed up + nick = (char*)RFIFOP(fd,2); // speed up RFIFOB(fd,25) = '\0'; // to be sure that the player name have at maximum 23 characters //printf("Ignore: char '%s' state: %d\n", nick, RFIFOB(fd,26)); WFIFOW(fd,0) = 0x0d1; // R 00d1 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail WFIFOB(fd,2) = RFIFOB(fd,26); // do nothing only if nick can not exist - if (strlen(nick) < 4) { + if (strlen(nick) < 4) { WFIFOB(fd,3) = 1; // fail WFIFOSET(fd, packet_len_table[0x0d1]); if (RFIFOB(fd,26) == 0) // type @@ -9669,7 +10214,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data *sd) { // Rewritten by clif_wis_message(fd, wisp_server_name, "This player is already blocked.", strlen("This player is already blocked.") + 1); if (strcmp(wisp_server_name, nick) == 0) { // to found possible bot users who automaticaly ignore people. sprintf(output, "Character '%s' (account: %d) has tried AGAIN to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name); - intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output, strlen(output) + 1); + intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output); } return; } else if (pos == -1 && sd->ignore[i].name[0] == '\0') @@ -9682,7 +10227,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data *sd) { // Rewritten by WFIFOSET(fd, packet_len_table[0x0d1]); if (strcmp(wisp_server_name, nick) == 0) { // to found possible bot users who automaticaly ignore people. sprintf(output, "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name); - intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output, strlen(output) + 1); + intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output); // send something to be inform and force bot to ignore twice... If GM receiving block + block again, it's a bot :) clif_wis_message(fd, wisp_server_name, "Add me in your ignore list, doesn't block my wisps.", strlen("Add me in your ignore list, doesn't block my wisps.") + 1); } @@ -9692,7 +10237,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data *sd) { // Rewritten by clif_wis_message(fd, wisp_server_name, "You can not block more people.", strlen("You can not block more people.") + 1); if (strcmp(wisp_server_name, nick) == 0) { // to found possible bot users who automaticaly ignore people. sprintf(output, "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name); - intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output, strlen(output) + 1); + intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output); } } // allow action (we remove all same nicks if they exist) @@ -9701,7 +10246,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data *sd) { // Rewritten by for(i = 0; i < MAX_IGNORE_LIST; i++) if (strcmp(sd->ignore[i].name, nick) == 0) { memset(sd->ignore[i].name, 0, sizeof(sd->ignore[i].name)); - if (pos != -1) { + if (pos == -1) { WFIFOB(fd,3) = 0; // success WFIFOSET(fd, packet_len_table[0x0d1]); pos = i; // don't break, to remove ALL same nick @@ -9753,6 +10298,38 @@ void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd) { // Rewritten return; } +/*========================================== + * Wis‹‘”ÛƒŠƒXƒg + *------------------------------------------ + */ + int pstrcmp(const void *a, const void *b) +{ + return strcmp((char *)a, (char *)b); +} +void clif_parse_PMIgnoreList(int fd,struct map_session_data *sd) +{ + int i,j=0,count=0; + + qsort (sd->ignore[0].name, MAX_IGNORE_LIST, sizeof(sd->ignore[0].name), pstrcmp); + for(i = 0; i < MAX_IGNORE_LIST; i++){ //’†g‚ª‚ ‚é‚̂𔂦‚é + if(sd->ignore[i].name[0] != 0) + count++; + } + WFIFOW(fd,0) = 0xd4; + WFIFOW(fd,2) = 4 + (24 * count); + for(i = 0; i < MAX_IGNORE_LIST; i++){ + if(sd->ignore[i].name[0] != 0){ + memcpy(WFIFOP(fd, 4 + j * 24),sd->ignore[i].name, 24); + j++; + } + } + WFIFOSET(fd, WFIFOW(fd,2)); + if(count >= MAX_IGNORE_LIST) //–žƒ^ƒ“‚È‚çÅŒã‚Ì1ŒÂ‚ðÁ‚· + sd->ignore[MAX_IGNORE_LIST - 1].name[0] = 0; + + return; +} + void clif_parse_skillMessage(int fd, struct map_session_data *sd) { // Added by RoVeRT int skillid,skilllv, x, y; char *mes; @@ -9763,7 +10340,7 @@ void clif_parse_skillMessage(int fd, struct map_session_data *sd) { // Added by y = RFIFOB(fd,6); x = RFIFOB(fd,8); - mes = RFIFOP(fd,10); + mes = (char*)RFIFOP(fd,10); // skill 220 = graffiti // printf("skill: %d %d location: %3d %3d message: %s\n", skillid, skilllv, x, y, (char*)mes); @@ -9795,11 +10372,11 @@ void clif_parse_sn_doridori(int fd, struct map_session_data *sd) { * ƒXƒpƒmƒr‚Ì”š—ô”g“® *------------------------------------------ */ -void clif_parse_sn_explosionspirits(int fd, struct map_session_data *sd) +void clif_parse_sn_explosionspirits(int fd, struct map_session_data *sd) { if(sd){ int nextbaseexp=pc_nextbaseexp(sd); - struct pc_base_job s_class = pc_calc_base_job(sd->status.class); + struct pc_base_job s_class = pc_calc_base_job(sd->status.class_); if (battle_config.etc_log){ if(nextbaseexp != 0) printf("SuperNovice explosionspirits!! %d %d %d %d\n",sd->bl.id,s_class.job,sd->status.base_exp,(int)((double)1000*sd->status.base_exp/nextbaseexp)); @@ -9808,7 +10385,7 @@ void clif_parse_sn_explosionspirits(int fd, struct map_session_data *sd) } if(s_class.job == 23 && sd->status.base_exp > 0 && nextbaseexp > 0 && (int)((double)1000*sd->status.base_exp/nextbaseexp)%100==0){ clif_skill_nodamage(&sd->bl,&sd->bl,MO_EXPLOSIONSPIRITS,5,1); - skill_status_change_start(&sd->bl,SkillStatusChangeTable[MO_EXPLOSIONSPIRITS],5,0,0,0,skill_get_time(MO_EXPLOSIONSPIRITS,5),0 ); + status_change_start(&sd->bl,SkillStatusChangeTable[MO_EXPLOSIONSPIRITS],5,0,0,0,skill_get_time(MO_EXPLOSIONSPIRITS,5),0 ); } } return; @@ -9839,7 +10416,7 @@ void clif_parse_friends_list_add(int fd, struct map_session_data *sd) { struct map_session_data *f_sd; int i; - f_sd = map_nick2sd(RFIFOP(fd,2)); + f_sd = map_nick2sd((char*)RFIFOP(fd,2)); // Friend doesn't exist (no player with this name) if (f_sd == NULL) { @@ -9917,9 +10494,28 @@ void clif_parse_GMkillall(int fd,struct map_session_data *sd) return; } +/*========================================== + * ƒpƒPƒbƒgƒfƒoƒbƒO + *------------------------------------------ + */ +void clif_parse_debug(int fd,struct map_session_data *sd) +{ + int i, cmd; + + cmd = RFIFOW(fd,0); + + printf("packet debug 0x%4X\n",cmd); + printf("---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F"); + for(i=0;i<packet_db[sd->packet_ver][cmd].len;i++){ + if((i&15)==0) + printf("\n%04X ",i); + printf("%02X ",RFIFOB(fd,i)); + } + printf("\n"); +} + // functions list -static void (*clif_parse_func_table[7][0x220])() = { - { +static void (*clif_parse_func_table[MAX_PACKET_DB])(int, struct map_session_data *) = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -9951,11 +10547,11 @@ static void (*clif_parse_func_table[7][0x220])() = { NULL, clif_parse_HowManyConnections, NULL, NULL, NULL, clif_parse_NpcBuySellSelected, NULL, NULL, clif_parse_NpcBuyListSend, clif_parse_NpcSellListSend, NULL, NULL, clif_parse_GMKick, NULL, clif_parse_GMkillall, clif_parse_PMIgnore, // d0 - clif_parse_PMIgnoreAll, NULL, NULL, NULL, NULL, clif_parse_CreateChatRoom, NULL, NULL, + clif_parse_PMIgnoreAll, NULL, NULL, clif_parse_PMIgnoreList, NULL, clif_parse_CreateChatRoom, NULL, NULL, NULL, clif_parse_ChatAddMember, NULL, NULL, NULL, NULL, clif_parse_ChatRoomStatusChange, NULL, // e0 clif_parse_ChangeChatOwner, NULL, clif_parse_KickFromChat, clif_parse_ChatLeave, clif_parse_TradeRequest, NULL, clif_parse_TradeAck, NULL, - clif_parse_TradeAddItem, NULL, NULL, clif_parse_TradeOk, NULL, clif_parse_TradeCansel, NULL, clif_parse_TradeCommit, + clif_parse_TradeAddItem, NULL, NULL, clif_parse_TradeOk, NULL, clif_parse_TradeCancel, NULL, clif_parse_TradeCommit, // f0 NULL, NULL, NULL, clif_parse_MoveToKafra, NULL, clif_parse_MoveFromKafra, NULL, clif_parse_CloseKafra, NULL, clif_parse_CreateParty, NULL, NULL, clif_parse_PartyInvite, NULL, NULL, clif_parse_ReplyPartyInvite, @@ -9975,7 +10571,7 @@ static void (*clif_parse_func_table[7][0x220])() = { // 140 clif_parse_MapMove, NULL, NULL, clif_parse_NpcAmountInput, NULL, NULL, clif_parse_NpcCloseClicked, NULL, - NULL, clif_parse_GMReqNoChat, NULL, NULL, NULL, clif_parse_GuildCheckMaster, NULL, clif_parse_GuildReqeustInfo, + NULL, clif_parse_GMReqNoChat, NULL, NULL, NULL, clif_parse_GuildCheckMaster, NULL, clif_parse_GuildRequestInfo, // 150 NULL, clif_parse_GuildRequestEmblem, NULL, clif_parse_GuildChangeEmblem, NULL, clif_parse_GuildChangeMemberPosition, NULL, NULL, NULL, clif_parse_GuildLeave, NULL, clif_parse_GuildExplusion, NULL, clif_parse_GuildBreak, NULL, NULL, @@ -10010,7 +10606,8 @@ static void (*clif_parse_func_table[7][0x220])() = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, clif_parse_sn_doridori, clif_parse_CreateParty2, NULL, NULL, NULL, NULL, clif_parse_sn_explosionspirits, NULL, NULL, // 1f0 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, clif_parse_ReqAdopt, + NULL, NULL, NULL, NULL, NULL, NULL, // 200 NULL, NULL, clif_parse_friends_list_add, clif_parse_friends_list_remove, NULL, NULL, NULL, NULL, @@ -10020,13 +10617,6 @@ static void (*clif_parse_func_table[7][0x220])() = { #if 0 case 0xd3: clif_parse_IgnoreList #endif - }, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {NULL} }; /*========================================== @@ -10035,28 +10625,33 @@ static void (*clif_parse_func_table[7][0x220])() = { *------------------------------------------ */ static int clif_parse(int fd) { - int packet_len = 0, cmd, packet_ver; + int packet_len = 0, cmd, packet_ver, dump = 0; struct map_session_data *sd; - sd = session[fd]->session_data; + sd = (struct map_session_data*)session[fd]->session_data; // Ú‘±‚ªØ‚ê‚Ä‚é‚̂ŌãŽn–– if (!chrif_isconnect() || session[fd]->eof) { // charŽI‚ÉŒq‚ª‚Á‚ĂȂ¢ŠÔ‚ÍÚ‘±‹ÖŽ~ (!chrif_isconnect()) if (sd && sd->state.auth) { - if (chrif_isconnect()) - clif_quitsave(fd, sd); + clif_quitsave(fd, sd); // the function doesn't send to inter-server/char-server if it is not connected [Yor] if (sd->status.name != NULL) - printf("Player [%s] has logged off your server.\n", sd->status.name); // Player logout display [Valaris] + sprintf(tmp_output,"%sCharacter '"CL_WHITE"%s"CL_RESET"' logged off.\n", (pc_isGM(sd))?"GM ":"",sd->status.name); // Player logout display [Valaris] else - printf("Player with account [%d] has logged off your server.\n", sd->bl.id); // Player logout display [Yor] + sprintf(tmp_output,"%sCharacter with Account ID '"CL_WHITE"%d"CL_RESET"' logged off.\n", (pc_isGM(sd))?"GM ":"", sd->bl.id); // Player logout display [Yor] } else if (sd) { // not authentified! (refused by char-server or disconnect before to be authentified) - printf("Player with account [%d] has logged off your server (not auth account).\n", sd->bl.id); // Player logout display [Yor] - map_deliddb(&sd->bl); // account_id has been included in the DB before auth answer + sprintf(tmp_output,"Player not authenticated with Account ID '"CL_WHITE"%d"CL_RESET"' logged off.\n", sd->bl.id); // Player logout display [Yor] +// if (chrif_isconnect()) +// clif_quitsave(fd, sd); + map_deliddb(&sd->bl); // account_id has been included in the DB before auth answer [Yor] +// sd = 0; + } else { + unsigned char *ip = (unsigned char *) &session[fd]->client_addr.sin_addr; + sprintf(tmp_output,"Player not identified with IP '"CL_WHITE"%d.%d.%d.%d"CL_RESET"' logged off.\n", ip[0],ip[1],ip[2],ip[3]); } + ShowInfo(tmp_output); close(fd); - if (sd) // ’ljÁ - - map_deliddb(&sd->bl); // ’ljÁ +// if (sd) // ’ljÁ +// map_deliddb(&sd->bl); // ’ljÁ delete_session(fd); return 0; } @@ -10064,7 +10659,7 @@ static int clif_parse(int fd) { if (RFIFOREST(fd) < 2) return 0; - //printf("clif_parse: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd)); +// printf("clif_parse: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd)); cmd = RFIFOW(fd,0); @@ -10084,7 +10679,8 @@ static int clif_parse(int fd) { RFIFOSKIP(fd,2); break; case 0x7532: // Ú‘±‚ÌØ’f - session[fd]->eof = 1; + close(fd); + session[fd]->eof=1; break; } return 0; @@ -10092,119 +10688,135 @@ static int clif_parse(int fd) { // get packet version before to parse packet_ver = 0; - if (sd) + if (sd) { packet_ver = sd->packet_ver; + if (packet_ver < 0 || packet_ver > MAX_PACKET_VER) { // unusual, but just in case + close(fd); + session[fd]->eof = 1; + printf("clif_parse: session #%d, bad packet version -> disconnected.\n", fd); + return 0; + } // check authentification packet to know packet version - else { + } else { + // packet DB + if (IS_PACKET_DB_VER (cmd)) { + if (RFIFOREST(fd) >= packet_db[clif_config.packet_db_ver][cmd].len && + (RFIFOB(fd,packet_db[clif_config.packet_db_ver][cmd].pos[4]) == 0 || + RFIFOB(fd,packet_db[clif_config.packet_db_ver][cmd].pos[4]) == 1)) {// 00 = Female, 01 = Male + packet_ver = clif_config.packet_db_ver; + } // 0x72 - if (cmd == 0x72) { + } else if (cmd == 0x72) { if (RFIFOREST(fd) >= 39 && (RFIFOB(fd,38) == 0 || RFIFOB(fd,38) == 1)) // 00 = Female, 01 = Male - packet_ver = 7; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + packet_ver = 7; // 7: 13july04 else if (RFIFOREST(fd) >= 22 && (RFIFOB(fd,21) == 0 || RFIFOB(fd,21) == 1)) // 00 = Female, 01 = Male - packet_ver = 6; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + packet_ver = 6; // 6: 7july04 else if (RFIFOREST(fd) >= 19 && (RFIFOB(fd,18) == 0 || RFIFOB(fd,18) == 1)) // 00 = Female, 01 = Male - packet_ver = 5; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + packet_ver = 5; // 5: old // else probably incomplete packet else if (RFIFOREST(fd) < 19) return 0; // 0x7E } else if (cmd == 0x7E) { if (RFIFOREST(fd) >= 37 && (RFIFOB(fd,36) == 0 || RFIFOB(fd,36) == 1)) // 00 = Female, 01 = Male - packet_ver = 9; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + packet_ver = 9; // 9: 9aug04/16aug04/17aug04 else if (RFIFOREST(fd) >= 33 && (RFIFOB(fd,32) == 0 || RFIFOB(fd,32) == 1)) // 00 = Female, 01 = Male - packet_ver = 8; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + packet_ver = 8; // 8: 26july04 // else probably incomplete packet else if (RFIFOREST(fd) < 33) return 0; // 0xF5 - } else { + } else if (cmd == 0xF5) { if (RFIFOREST(fd) >= 34 && (RFIFOB(fd,33) == 0 || RFIFOB(fd,33) == 1)) // 00 = Female, 01 = Male - packet_ver = 10; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + packet_ver = 10; // 10: 6sept04 else if (RFIFOREST(fd) >= 33 && (RFIFOB(fd,32) == 0 || RFIFOB(fd,32) == 1)) // 00 = Female, 01 = Male - packet_ver = 12; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + packet_ver = 12; // 12: 18oct04 else if (RFIFOREST(fd) >= 32 && (RFIFOB(fd,31) == 0 || RFIFOB(fd,31) == 1)) // 00 = Female, 01 = Male - packet_ver = 11; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) - else if (RFIFOREST(fd) >= 29 && (RFIFOB(fd,28) == 0 || RFIFOB(fd,28) == 1)) // 00 = Female, 01 = Male - packet_ver = 13; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) + packet_ver = 11; // 11: 21sept04 + else if (RFIFOREST(fd) >= 29 && (RFIFOB(fd,28) == 0 || RFIFOB(fd,28) == 1)) { // 00 = Female, 01 = Male + if (RFIFOL(fd,3) > 700000 && RFIFOL(fd,10) >= 150000 && RFIFOL(fd,10) < 5000000) // account id / char id (more than 5.000.000 characters?) [Yor] + packet_ver = 15; // 14: 6dec04 + else + packet_ver = 13; // 13: 25oct04 (by [Yor]) + } // else probably incomplete packet else if (RFIFOREST(fd) < 29) return 0; + // 0x9B + } else if (cmd == 0x9B) { + if (RFIFOREST(fd) >= 32 && (RFIFOB(fd,31) == 0 || RFIFOB(fd,31) == 1)) // 00 = Female, 01 = Male + packet_ver = 16; // 16: 10jan05 + else if (RFIFOREST(fd) < 32) + return 0; + } else { + // unknown client? leave packet ver as 0 so it'll disconnect anyway } + // check if version is accepted - if ((packet_ver == 5 && (battle_config.packet_ver_flag & 1) == 0) || - (packet_ver == 6 && (battle_config.packet_ver_flag & 2) == 0) || - (packet_ver == 7 && (battle_config.packet_ver_flag & 4) == 0) || - (packet_ver == 8 && (battle_config.packet_ver_flag & 8) == 0) || - (packet_ver == 9 && (battle_config.packet_ver_flag & 16) == 0) || - (packet_ver == 10 && (battle_config.packet_ver_flag & 32) == 0) || - (packet_ver == 11 && (battle_config.packet_ver_flag & 64) == 0) || - (packet_ver == 12 && (battle_config.packet_ver_flag & 128) == 0) || - (packet_ver == 13 && (battle_config.packet_ver_flag & 256) == 0)) { + if (packet_ver < 5 || // reject really old client versions + (packet_ver <= 9 && (battle_config.packet_ver_flag & 1) == 0) || // older than 6sept04 + (packet_ver == 10 && (battle_config.packet_ver_flag & 2) == 0) || + (packet_ver == 11 && (battle_config.packet_ver_flag & 4) == 0) || + (packet_ver == 12 && (battle_config.packet_ver_flag & 8) == 0) || + (packet_ver == 13 && (battle_config.packet_ver_flag & 16) == 0) || + (packet_ver == 14 && (battle_config.packet_ver_flag & 32) == 0) || + (packet_ver == 15 && (battle_config.packet_ver_flag & 64) == 0) || + (packet_ver == 16 && (battle_config.packet_ver_flag & 128) == 0) || + packet_ver > MAX_PACKET_VER || // no packet version support yet + // identified version, but unknown client? + (!sd && packet_db[packet_ver][cmd].func != clif_parse_WantToConnection)) { WFIFOW(fd,0) = 0x6a; WFIFOB(fd,2) = 5; // 05 = Game's EXE is not the latest version WFIFOSET(fd,23); - session[fd]->eof = 1; + clif_setwaitclose(fd); return 0; } } // ƒQ[ƒ€—pˆÈŠOƒpƒPƒbƒg‚©A”FØ‚ðI‚¦‚é‘O‚É0072ˆÈŠO‚ª—ˆ‚½‚çAØ’f‚·‚é - if (packet_ver < 5 || packet_ver > 13 || // if packet is not inside these values: session is incorrect?? or auth packet is unknown - cmd >= 0x220 || packet_size_table[packet_ver-5][cmd] == 0) { + if (cmd >= MAX_PACKET_DB || packet_db[packet_ver][cmd].len == 0) { // if packet is not inside these values: session is incorrect?? or auth packet is unknown if (!fd) return 0; + close(fd); session[fd]->eof = 1; printf("clif_parse: session #%d, packet 0x%x (%d bytes received) -> disconnected.\n", fd, cmd, RFIFOREST(fd)); return 0; } // ƒpƒPƒbƒg’·‚ðŒvŽZ - packet_len = packet_size_table[packet_ver-5][cmd]; + packet_len = packet_db[packet_ver][cmd].len; if (packet_len == -1) { if (RFIFOREST(fd) < 4) return 0; // ‰Â•Ï’·ƒpƒPƒbƒg‚Å’·‚³‚ÌŠ‚܂Ńf[ƒ^‚ª—ˆ‚ĂȂ¢ packet_len = RFIFOW(fd,2); if (packet_len < 4 || packet_len > 32768) { - session[fd]->eof = 1; + close(fd); + session[fd]->eof =1; return 0; } } if (RFIFOREST(fd) < packet_len) return 0; // ‚Ü‚¾1ƒpƒPƒbƒg•ªƒf[ƒ^‚ª‘µ‚Á‚ĂȂ¢ + #if DUMP_ALL_PACKETS + dump = 1; + #endif + if (sd && sd->state.auth == 1 && sd->state.waitingdisconnect == 1) { // Ø’f‘Ò‚¿‚ÌꇃpƒPƒbƒg‚ðˆ—‚µ‚È‚¢ - } else if (packet_ver < 8 && clif_parse_func_table[0][cmd]) { // packet version 5-6-7 use same functions, but size are different + } else if (packet_db[packet_ver][cmd].func) { // packet version 5-6-7 use same functions, but size are different // ƒpƒPƒbƒgˆ— - clif_parse_func_table[0][cmd](fd, sd); - } else if (packet_ver >= 8 && clif_parse_func_table[packet_ver - 7][cmd]) { - // ƒpƒPƒbƒgˆ— - clif_parse_func_table[packet_ver - 7][cmd](fd, sd); + packet_db[packet_ver][cmd].func(fd, sd); } else { // •s–¾‚ȃpƒPƒbƒg if (battle_config.error_log) { - if (fd) - printf("\nclif_parse: session #%d, packet 0x%x, lenght %d\n", fd, cmd, packet_len); -#ifdef DUMP_UNKNOWN_PACKET +#if DUMP_UNKNOWN_PACKET { int i; FILE *fp; char packet_txt[256] = "save/packet.txt"; time_t now; - printf("---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F"); - for(i = 0; i < packet_len; i++) { - if ((i & 15) == 0) - printf("\n%04X ",i); - printf("%02X ", RFIFOB(fd,i)); - } - if (sd && sd->state.auth) { - if (sd->status.name != NULL) - printf("\nAccount ID %d, character ID %d, player name %s.\n", - sd->status.account_id, sd->status.char_id, sd->status.name); - else - printf("\nAccount ID %d.\n", sd->bl.id); - } else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified) - printf("\nAccount ID %d.\n", sd->bl.id); + dump = 1; if ((fp = fopen(packet_txt, "a")) == NULL) { printf("clif.c: cant write [%s] !!! data is lost !!!\n", packet_txt); @@ -10233,218 +10845,618 @@ static int clif_parse(int fd) { #endif } } + + if (dump) { + int i; + if (fd) + printf("\nclif_parse: session #%d, packet 0x%x, lenght %d\n", fd, cmd, packet_len); + printf("---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F"); + for(i = 0; i < packet_len; i++) { + if ((i & 15) == 0) + printf("\n%04X ",i); + printf("%02X ", RFIFOB(fd,i)); + } + if (sd && sd->state.auth) { + if (sd->status.name != NULL) + printf("\nAccount ID %d, character ID %d, player name %s.\n", + sd->status.account_id, sd->status.char_id, sd->status.name); + else + printf("\nAccount ID %d.\n", sd->bl.id); + } else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified) + printf("\nAccount ID %d.\n", sd->bl.id); + } + RFIFOSKIP(fd, packet_len); return 0; } /*========================================== + * ƒpƒPƒbƒgƒf[ƒ^ƒx[ƒX“ǂݞ‚Ý + *------------------------------------------ + */ +static int packetdb_readdb(void) +{ + FILE *fp; + char line[1024]; + int ln=0; + int cmd,j,k,packet_ver; + char *str[64],*p,*str2[64],*p2,w1[64],w2[64]; + + struct { + void (*func)(int, struct map_session_data *); + char *name; + } clif_parse_func[]={ + {clif_parse_WantToConnection,"wanttoconnection"}, + {clif_parse_LoadEndAck,"loadendack"}, + {clif_parse_TickSend,"ticksend"}, + {clif_parse_WalkToXY,"walktoxy"}, + {clif_parse_QuitGame,"quitgame"}, + {clif_parse_GetCharNameRequest,"getcharnamerequest"}, + {clif_parse_GlobalMessage,"globalmessage"}, + {clif_parse_MapMove,"mapmove"}, + {clif_parse_ChangeDir,"changedir"}, + {clif_parse_Emotion,"emotion"}, + {clif_parse_HowManyConnections,"howmanyconnections"}, + {clif_parse_ActionRequest,"actionrequest"}, + {clif_parse_Restart,"restart"}, + {clif_parse_Wis,"wis"}, + {clif_parse_GMmessage,"gmmessage"}, + {clif_parse_TakeItem,"takeitem"}, + {clif_parse_DropItem,"dropitem"}, + {clif_parse_UseItem,"useitem"}, + {clif_parse_EquipItem,"equipitem"}, + {clif_parse_UnequipItem,"unequipitem"}, + {clif_parse_NpcClicked,"npcclicked"}, + {clif_parse_NpcBuySellSelected,"npcbuysellselected"}, + {clif_parse_NpcBuyListSend,"npcbuylistsend"}, + {clif_parse_NpcSellListSend,"npcselllistsend"}, + {clif_parse_CreateChatRoom,"createchatroom"}, + {clif_parse_ChatAddMember,"chataddmember"}, + {clif_parse_ChatRoomStatusChange,"chatroomstatuschange"}, + {clif_parse_ChangeChatOwner,"changechatowner"}, + {clif_parse_KickFromChat,"kickfromchat"}, + {clif_parse_ChatLeave,"chatleave"}, + {clif_parse_TradeRequest,"traderequest"}, + {clif_parse_TradeAck,"tradeack"}, + {clif_parse_TradeAddItem,"tradeadditem"}, + {clif_parse_TradeOk,"tradeok"}, + {clif_parse_TradeCancel,"tradecancel"}, + {clif_parse_TradeCommit,"tradecommit"}, + {clif_parse_StopAttack,"stopattack"}, + {clif_parse_PutItemToCart,"putitemtocart"}, + {clif_parse_GetItemFromCart,"getitemfromcart"}, + {clif_parse_RemoveOption,"removeoption"}, + {clif_parse_ChangeCart,"changecart"}, + {clif_parse_StatusUp,"statusup"}, + {clif_parse_SkillUp,"skillup"}, + {clif_parse_UseSkillToId,"useskilltoid"}, + {clif_parse_UseSkillToPos,"useskilltopos"}, + {clif_parse_UseSkillMap,"useskillmap"}, + {clif_parse_RequestMemo,"requestmemo"}, + {clif_parse_ProduceMix,"producemix"}, + {clif_parse_NpcSelectMenu,"npcselectmenu"}, + {clif_parse_NpcNextClicked,"npcnextclicked"}, + {clif_parse_NpcAmountInput,"npcamountinput"}, + {clif_parse_NpcStringInput,"npcstringinput"}, + {clif_parse_NpcCloseClicked,"npccloseclicked"}, + {clif_parse_ItemIdentify,"itemidentify"}, + {clif_parse_SelectArrow,"selectarrow"}, + {clif_parse_AutoSpell,"autospell"}, + {clif_parse_UseCard,"usecard"}, + {clif_parse_InsertCard,"insertcard"}, + {clif_parse_SolveCharName,"solvecharname"}, + {clif_parse_ResetChar,"resetchar"}, + {clif_parse_LGMmessage,"lgmmessage"}, + {clif_parse_MoveToKafra,"movetokafra"}, + {clif_parse_MoveFromKafra,"movefromkafra"}, + {clif_parse_MoveToKafraFromCart,"movetokafrafromcart"}, + {clif_parse_MoveFromKafraToCart,"movefromkafratocart"}, + {clif_parse_CloseKafra,"closekafra"}, + {clif_parse_CreateParty,"createparty"}, + {clif_parse_CreateParty2,"createparty2"}, + {clif_parse_PartyInvite,"partyinvite"}, + {clif_parse_ReplyPartyInvite,"replypartyinvite"}, + {clif_parse_LeaveParty,"leaveparty"}, + {clif_parse_RemovePartyMember,"removepartymember"}, + {clif_parse_PartyChangeOption,"partychangeoption"}, + {clif_parse_PartyMessage,"partymessage"}, + {clif_parse_CloseVending,"closevending"}, + {clif_parse_VendingListReq,"vendinglistreq"}, + {clif_parse_PurchaseReq,"purchasereq"}, + {clif_parse_OpenVending,"openvending"}, + {clif_parse_CreateGuild,"createguild"}, + {clif_parse_GuildCheckMaster,"guildcheckmaster"}, + {clif_parse_GuildRequestInfo,"guildrequestinfo"}, + {clif_parse_GuildChangePositionInfo,"guildchangepositioninfo"}, + {clif_parse_GuildChangeMemberPosition,"guildchangememberposition"}, + {clif_parse_GuildRequestEmblem,"guildrequestemblem"}, + {clif_parse_GuildChangeEmblem,"guildchangeemblem"}, + {clif_parse_GuildChangeNotice,"guildchangenotice"}, + {clif_parse_GuildInvite,"guildinvite"}, + {clif_parse_GuildReplyInvite,"guildreplyinvite"}, + {clif_parse_GuildLeave,"guildleave"}, + {clif_parse_GuildExplusion,"guildexplusion"}, + {clif_parse_GuildMessage,"guildmessage"}, + {clif_parse_GuildRequestAlliance,"guildrequestalliance"}, + {clif_parse_GuildReplyAlliance,"guildreplyalliance"}, + {clif_parse_GuildDelAlliance,"guilddelalliance"}, + {clif_parse_GuildOpposition,"guildopposition"}, + {clif_parse_GuildBreak,"guildbreak"}, + {clif_parse_PetMenu,"petmenu"}, + {clif_parse_CatchPet,"catchpet"}, + {clif_parse_SelectEgg,"selectegg"}, + {clif_parse_SendEmotion,"sendemotion"}, + {clif_parse_ChangePetName,"changepetname"}, + {clif_parse_GMKick,"gmkick"}, + {clif_parse_GMHide,"gmhide"}, + {clif_parse_GMReqNoChat,"gmreqnochat"}, + {clif_parse_GMReqNoChatCount,"gmreqnochatcount"}, + {clif_parse_sn_doridori,"sndoridori"}, + {clif_parse_sn_explosionspirits,"snexplosionspirits"}, + {clif_parse_PMIgnore,"wisexin"}, + {clif_parse_PMIgnoreList,"wisexlist"}, + {clif_parse_PMIgnoreAll,"wisall"}, + {clif_parse_friends_list_add,"friendslistadd"}, + {clif_parse_friends_list_remove,"friendslistremove"}, + {clif_parse_GMkillall,"killall"}, + {clif_parse_Recall,"summon"}, + {clif_parse_GM_Monster_Item,"itemmonster"}, + {clif_parse_Shift,"shift"}, + {clif_parse_debug,"debug"}, + + {NULL,NULL} + }; + + if( (fp=fopen("db/packet_db.txt","r"))==NULL ){ + printf("can't read db/packet_db.txt\n"); + return 1; + } + + clif_config.packet_db_ver = MAX_PACKET_VER; + packet_ver = MAX_PACKET_VER; // read into packet_db's version by default + + while(fgets(line,1020,fp)){ + if(line[0]=='/' && line[1]=='/') + continue; + if (sscanf(line,"%[^:]: %[^\r\n]",w1,w2) == 2) { + if(strcmpi(w1,"packet_ver")==0) { + packet_ver = atoi(w2); + // copy from previous version into new version and continue + // - indicating all following packets should be read into the newer version + // -- on 2nd thought, rereading everything isn't the best thing to do... + // memcpy(&packet_db[packet_ver], &packet_db[packet_ver - 1], sizeof(packet_db[0])); + continue; + } else if(strcmpi(w1,"packet_db_ver")==0) { + // optional: if you do not wish to read multiple versions from the packet_db, + // remove all "packet_ver: ##" lines, and define the packet DB version with this + if(strcmpi(w2,"default")==0) + clif_config.packet_db_ver = MAX_PACKET_VER; + else { + // to manually set the packet DB version + clif_config.packet_db_ver = atoi(w2); + // check for invalid version + if (clif_config.packet_db_ver > MAX_PACKET_VER || + clif_config.packet_db_ver < 0) + clif_config.packet_db_ver = MAX_PACKET_VER; + } + continue; + } else if(strcmpi(w1,"enable_packet_db")==0) { + // whether we want to allow identifying clients via the packet DB + clif_config.enable_packet_db = battle_config_switch(w2); + // if we don't want to read the packet DB, and use hardcoded values only + if (!clif_config.enable_packet_db) + return 0; + continue; + } else if(strcmpi(w1,"prefer_packet_db")==0) { + // whether the packet DB takes higher precedence over the hardcoded one (type 1) + // and whether to overwrite predefined packet length and functions when reading + // from the DB (type 2) + clif_config.prefer_packet_db = battle_config_switch(w2); // not used for now + continue; + } + } + + memset(str,0,sizeof(str)); + for(j=0,p=line;j<4 && p;j++){ + str[j]=p; + p=strchr(p,','); + if(p) *p++=0; + } + if(str[0]==NULL) + continue; + cmd=strtol(str[0],(char **)NULL,0); + if(cmd<=0 || cmd>=MAX_PACKET_DB) + continue; + if(str[1]==NULL){ + sprintf(tmp_output, "packet_db: packet len error\n"); + ShowError(tmp_output); + continue; + } + k = atoi(str[1]); + // if (packet_db[packet_ver][cmd].len != k && clif_config.prefer_packet_db) // not used for now + packet_db[packet_ver][cmd].len = k; + + if(str[2]==NULL){ + ln++; + continue; + } + for(j=0;j<sizeof(clif_parse_func)/sizeof(clif_parse_func[0]);j++){ + if(clif_parse_func[j].name != NULL && + strcmp(str[2],clif_parse_func[j].name)==0){ + // if (packet_db[packet_ver][cmd].func != clif_parse_func[j].func && !clif_config.prefer_packet_db) + // break; // not used for now + packet_db[packet_ver][cmd].func = clif_parse_func[j].func; + break; + } + } + // set the identifying cmd for the packet_db version + if (strcmp(str[2],"wanttoconnection")==0){ + clif_config.connect_cmd = cmd; + } + if(str[3]==NULL){ + sprintf(tmp_output, "packet_db: packet error\n"); + ShowError(tmp_output); + exit(1); + } + for(j=0,p2=str[3];p2;j++){ + str2[j]=p2; + p2=strchr(p2,':'); + if(p2) *p2++=0; + k = atoi(str2[j]); + // if (packet_db[packet_ver][cmd].pos[j] != k && clif_config.prefer_packet_db) // not used for now + packet_db[packet_ver][cmd].pos[j] = k; + } + + ln++; +// if(packet_db[clif_config.packet_db_ver][cmd].len > 2 /* && packet_db[cmd].pos[0] == 0 */) +// printf("packet_db ver %d: %d 0x%x %d %s %p\n",packet_ver,ln,cmd,packet_db[packet_ver][cmd].len,str[2],packet_db[packet_ver][cmd].func); + } + + fclose(fp); + sprintf(tmp_output,"Done reading packet version '"CL_WHITE"%d"CL_RESET"' in '"CL_WHITE"%s"CL_RESET"'.\n", clif_config.packet_db_ver, "db/packet_db.txt"); + ShowStatus(tmp_output); + return 0; + +} + +/*========================================== * *------------------------------------------ */ int do_init_clif(void) { -#ifndef __WIN32 int i; -#endif + clif_config.enable_packet_db = 1; // whether to use the packet DB for client connection + clif_config.packet_db_ver = -1; // the main packet version of the DB + clif_config.prefer_packet_db = 1; // whether the packet version takes precedence + clif_config.connect_cmd = 0xF5; // the default packet used for connecting to the server + + memset(packet_db,0,sizeof(packet_db)); + + // size of packet version 5 (old) + for(i=0;i<sizeof(packet_len_table)/sizeof(packet_len_table[0]);i++){ + packet_db[0][i].len = packet_len_table[i]; + } + // packet functions of version 5 (old) + for(i=0;i<sizeof(clif_parse_func_table)/sizeof(clif_parse_func_table[0]);i++){ + packet_db[0][i].func = clif_parse_func_table[i]; + } + + // using hardcoded packet values isn't necessary with packet_db now, + // but... just in case, i'll leave it to initialise for now ^^; + // init packet version 5 and lower + memcpy(&packet_db[1], &packet_db[0], sizeof(packet_db[0])); + memcpy(&packet_db[2], &packet_db[1], sizeof(packet_db[0])); + memcpy(&packet_db[3], &packet_db[2], sizeof(packet_db[0])); + memcpy(&packet_db[4], &packet_db[3], sizeof(packet_db[0])); + memcpy(&packet_db[5], &packet_db[4], sizeof(packet_db[0])); + +#ifndef PREFER_PACKET_DB // functions of packet version 5-6-7 are same, but size are different + // size of packet version 6 (7july04) + memcpy(&packet_db[6], &packet_db[5], sizeof(packet_db[0])); + packet_db[6][0x072].len = 22; + packet_db[6][0x085].len = 8; + packet_db[6][0x0a7].len = 13; + packet_db[6][0x113].len = 15; + packet_db[6][0x116].len = 15; + packet_db[6][0x190].len = 95; + // size of packet version 7 (13july04) + memcpy(&packet_db[7], &packet_db[6], sizeof(packet_db[0])); + packet_db[7][0x072].len = 39; + packet_db[7][0x085].len = 9; + packet_db[7][0x09b].len = 13; + packet_db[7][0x09f].len = 10; + packet_db[7][0x0a7].len = 17; + packet_db[7][0x113].len = 19; + packet_db[7][0x116].len = 19; + packet_db[7][0x190].len = 99; // init packet function calls for packet ver 8 - memcpy(clif_parse_func_table[1], clif_parse_func_table[0], sizeof(clif_parse_func_table[0])); - clif_parse_func_table[1][0x072] = clif_parse_DropItem; - clif_parse_func_table[1][0x07e] = clif_parse_WantToConnection; - clif_parse_func_table[1][0x085] = clif_parse_UseSkillToId; - clif_parse_func_table[1][0x089] = clif_parse_GetCharNameRequest; - clif_parse_func_table[1][0x08c] = clif_parse_UseSkillToPos; - clif_parse_func_table[1][0x094] = clif_parse_TakeItem; - clif_parse_func_table[1][0x09b] = clif_parse_WalkToXY; - clif_parse_func_table[1][0x09f] = clif_parse_ChangeDir; - clif_parse_func_table[1][0x0a2] = clif_parse_UseSkillToPos; - clif_parse_func_table[1][0x0a7] = clif_parse_SolveCharName; - clif_parse_func_table[1][0x0f3] = clif_parse_GlobalMessage; - clif_parse_func_table[1][0x0f5] = clif_parse_UseItem; - clif_parse_func_table[1][0x0f7] = clif_parse_TickSend; - clif_parse_func_table[1][0x113] = clif_parse_MoveToKafra; - clif_parse_func_table[1][0x116] = clif_parse_CloseKafra; - clif_parse_func_table[1][0x190] = clif_parse_MoveFromKafra; - clif_parse_func_table[1][0x193] = clif_parse_ActionRequest; + memcpy(packet_db[8], packet_db[7], sizeof(packet_db[0])); + packet_db[8][0x072].func = clif_parse_DropItem; + packet_db[8][0x07e].func = clif_parse_WantToConnection; + packet_db[8][0x085].func = clif_parse_UseSkillToId; + packet_db[8][0x089].func = clif_parse_GetCharNameRequest; + packet_db[8][0x08c].func = clif_parse_UseSkillToPos; + packet_db[8][0x094].func = clif_parse_TakeItem; + packet_db[8][0x09b].func = clif_parse_WalkToXY; + packet_db[8][0x09f].func = clif_parse_ChangeDir; + packet_db[8][0x0a2].func = clif_parse_UseSkillToPos; + packet_db[8][0x0a7].func = clif_parse_SolveCharName; + packet_db[8][0x0f3].func = clif_parse_GlobalMessage; + packet_db[8][0x0f5].func = clif_parse_UseItem; + packet_db[8][0x0f7].func = clif_parse_TickSend; + packet_db[8][0x113].func = clif_parse_MoveToKafra; + packet_db[8][0x116].func = clif_parse_CloseKafra; + packet_db[8][0x190].func = clif_parse_MoveFromKafra; + packet_db[8][0x193].func = clif_parse_ActionRequest; + // size of packet version 8 (26july04) + packet_db[8][0x072].len = 14; + packet_db[8][0x07e].len = 33; + packet_db[8][0x085].len = 20; + packet_db[8][0x089].len = 15; + packet_db[8][0x08c].len = 23; + packet_db[8][0x094].len = 10; + packet_db[8][0x09b].len = 6; + packet_db[8][0x09f].len = 13; + packet_db[8][0x0a2].len = 103; + packet_db[8][0x0a7].len = 12; + packet_db[8][0x0f3].len = -1; + packet_db[8][0x0f5].len = 17; + packet_db[8][0x0f7].len = 10; + packet_db[8][0x113].len = 16; + packet_db[8][0x116].len = 2; + packet_db[8][0x190].len = 26; + packet_db[8][0x193].len = 9; // init packet function calls for packet ver 9 (same function of packet version 8, but size are different) - memcpy(clif_parse_func_table[2], clif_parse_func_table[1], sizeof(clif_parse_func_table[0])); + memcpy(packet_db[9], packet_db[8], sizeof(packet_db[0])); + // size of packet version 9 (9aug04/16aug04/17aug04) + packet_db[9][0x072].len = 17; + packet_db[9][0x07e].len = 37; + packet_db[9][0x085].len = 26; + packet_db[9][0x089].len = 12; + packet_db[9][0x08c].len = 40; + packet_db[9][0x094].len = 13; + packet_db[9][0x09b].len = 15; + packet_db[9][0x09f].len = 12; + packet_db[9][0x0a2].len = 120; + packet_db[9][0x0a7].len = 11; +// packet_db[9][0x0f3].len = -1; + packet_db[9][0x0f5].len = 24; + packet_db[9][0x0f7].len = 13; + packet_db[9][0x113].len = 23; +// packet_db[9][0x116].len = 2; + packet_db[9][0x190].len = 26; + packet_db[9][0x193].len = 18; + // new packet + packet_db[9][0x20f].len = 10; + packet_db[9][0x210].len = 22; + packet_db[9][0x212].len = 26; + packet_db[9][0x213].len = 26; + packet_db[9][0x214].len = 42; // init packet function calls for packet ver 10 - memcpy(clif_parse_func_table[3], clif_parse_func_table[2], sizeof(clif_parse_func_table[0])); - clif_parse_func_table[3][0x072] = clif_parse_UseItem; - clif_parse_func_table[3][0x07e] = clif_parse_MoveToKafra; - clif_parse_func_table[3][0x085] = clif_parse_ActionRequest; - clif_parse_func_table[3][0x089] = clif_parse_WalkToXY; - clif_parse_func_table[3][0x08c] = clif_parse_UseSkillToPos; - clif_parse_func_table[3][0x094] = clif_parse_DropItem; - clif_parse_func_table[3][0x09b] = clif_parse_GetCharNameRequest; - clif_parse_func_table[3][0x09f] = clif_parse_GlobalMessage; - clif_parse_func_table[3][0x0a2] = clif_parse_SolveCharName; - clif_parse_func_table[3][0x0a7] = clif_parse_UseSkillToPos; - clif_parse_func_table[3][0x0f3] = clif_parse_ChangeDir; - clif_parse_func_table[3][0x0f5] = clif_parse_WantToConnection; - clif_parse_func_table[3][0x0f7] = clif_parse_CloseKafra; - clif_parse_func_table[3][0x113] = clif_parse_TakeItem; - clif_parse_func_table[3][0x116] = clif_parse_TickSend; - clif_parse_func_table[3][0x190] = clif_parse_UseSkillToId; - clif_parse_func_table[3][0x193] = clif_parse_MoveFromKafra; + memcpy(packet_db[10], packet_db[9], sizeof(packet_db[0])); + packet_db[10][0x072].func = clif_parse_UseItem; + packet_db[10][0x07e].func = clif_parse_MoveToKafra; + packet_db[10][0x085].func = clif_parse_ActionRequest; + packet_db[10][0x089].func = clif_parse_WalkToXY; + packet_db[10][0x08c].func = clif_parse_UseSkillToPos; + packet_db[10][0x094].func = clif_parse_DropItem; + packet_db[10][0x09b].func = clif_parse_GetCharNameRequest; + packet_db[10][0x09f].func = clif_parse_GlobalMessage; + packet_db[10][0x0a2].func = clif_parse_SolveCharName; + packet_db[10][0x0a7].func = clif_parse_UseSkillToPos; + packet_db[10][0x0f3].func = clif_parse_ChangeDir; + packet_db[10][0x0f5].func = clif_parse_WantToConnection; + packet_db[10][0x0f7].func = clif_parse_CloseKafra; + packet_db[10][0x113].func = clif_parse_TakeItem; + packet_db[10][0x116].func = clif_parse_TickSend; + packet_db[10][0x190].func = clif_parse_UseSkillToId; + packet_db[10][0x193].func = clif_parse_MoveFromKafra; + // size of packet version 10 (6sept04) + packet_db[10][0x072].len = 20; + packet_db[10][0x07e].len = 19; + packet_db[10][0x085].len = 23; + packet_db[10][0x089].len = 9; + packet_db[10][0x08c].len = 105; + packet_db[10][0x094].len = 17; + packet_db[10][0x09b].len = 14; + packet_db[10][0x09f].len = -1; + packet_db[10][0x0a2].len = 14; + packet_db[10][0x0a7].len = 25; + packet_db[10][0x0f3].len = 10; + packet_db[10][0x0f5].len = 34; + packet_db[10][0x0f7].len = 2; + packet_db[10][0x113].len = 11; + packet_db[10][0x116].len = 11; + packet_db[10][0x190].len = 22; + packet_db[10][0x193].len = 17; // init packet function calls for packet ver 11 (same function of packet version 10, but size are different) - memcpy(clif_parse_func_table[4], clif_parse_func_table[3], sizeof(clif_parse_func_table[0])); + memcpy(packet_db[11], packet_db[10], sizeof(packet_db[0])); + // size of packet version 11 (21sept04) + packet_db[11][0x072].len = 18; + packet_db[11][0x07e].len = 25; + packet_db[11][0x085].len = 9; + packet_db[11][0x089].len = 14; + packet_db[11][0x08c].len = 109; + packet_db[11][0x094].len = 19; + packet_db[11][0x09b].len = 10; +// packet_db[11][0x09f].len = -1; + packet_db[11][0x0a2].len = 10; + packet_db[11][0x0a7].len = 29; + packet_db[11][0x0f3].len = 18; + packet_db[11][0x0f5].len = 32; +// packet_db[11][0x0f7].len = 2; + packet_db[11][0x113].len = 14; + packet_db[11][0x116].len = 14; + packet_db[11][0x190].len = 14; + packet_db[11][0x193].len = 12; // init packet function calls for packet ver 12 (same function of packet version 11, but size are different) - memcpy(clif_parse_func_table[5], clif_parse_func_table[4], sizeof(clif_parse_func_table[0])); + memcpy(packet_db[12], packet_db[11], sizeof(packet_db[0])); + // size of packet version 12 (18oct04) + packet_db[12][0x072].len = 17; + packet_db[12][0x07e].len = 16; +// packet_db[12][0x085].len = 9; + packet_db[12][0x089].len = 6; + packet_db[12][0x08c].len = 103; + packet_db[12][0x094].len = 14; + packet_db[12][0x09b].len = 15; +// packet_db[12][0x09f].len = -1; + packet_db[12][0x0a2].len = 12; + packet_db[12][0x0a7].len = 23; + packet_db[12][0x0f3].len = 13; + packet_db[12][0x0f5].len = 33; +// packet_db[12][0x0f7].len = 2; + packet_db[12][0x113].len = 10; + packet_db[12][0x116].len = 10; + packet_db[12][0x190].len = 20; + packet_db[12][0x193].len = 26; // init packet function calls for packet ver 13 (same function of packet version 12, but size are different) - memcpy(clif_parse_func_table[6], clif_parse_func_table[5], sizeof(clif_parse_func_table[0])); - - // size of packet version 5 - memcpy(&packet_size_table[0], &packet_len_table, sizeof(packet_len_table)); - // size of packet version 6 - memcpy(&packet_size_table[1], &packet_size_table[0], sizeof(packet_len_table)); - packet_size_table[1][0x072] = 22; - packet_size_table[1][0x085] = 8; - packet_size_table[1][0x0a7] = 13; - packet_size_table[1][0x113] = 15; - packet_size_table[1][0x116] = 15; - packet_size_table[1][0x190] = 95; - // size of packet version 7 - memcpy(&packet_size_table[2], &packet_size_table[1], sizeof(packet_len_table)); - packet_size_table[2][0x072] = 39; - packet_size_table[2][0x085] = 9; - packet_size_table[2][0x09b] = 13; - packet_size_table[2][0x09f] = 10; - packet_size_table[2][0x0a7] = 17; - packet_size_table[2][0x113] = 19; - packet_size_table[2][0x116] = 19; - packet_size_table[2][0x190] = 99; - // size of packet version 8 - memcpy(&packet_size_table[3], &packet_size_table[2], sizeof(packet_len_table)); - packet_size_table[3][0x072] = 14; - packet_size_table[3][0x07e] = 33; - packet_size_table[3][0x085] = 20; - packet_size_table[3][0x089] = 15; - packet_size_table[3][0x08c] = 23; - packet_size_table[3][0x094] = 10; - packet_size_table[3][0x09b] = 6; - packet_size_table[3][0x09f] = 13; - packet_size_table[3][0x0a2] = 103; - packet_size_table[3][0x0a7] = 12; - packet_size_table[3][0x0f3] = -1; - packet_size_table[3][0x0f5] = 17; - packet_size_table[3][0x0f7] = 10; - packet_size_table[3][0x113] = 16; - packet_size_table[3][0x116] = 2; - packet_size_table[3][0x190] = 26; - packet_size_table[3][0x193] = 9; - // size of packet version 9 - memcpy(&packet_size_table[4], &packet_size_table[3], sizeof(packet_len_table)); - packet_size_table[4][0x072] = 17; - packet_size_table[4][0x07e] = 37; - packet_size_table[4][0x085] = 26; - packet_size_table[4][0x089] = 12; - packet_size_table[4][0x08c] = 40; - packet_size_table[4][0x094] = 13; - packet_size_table[4][0x09b] = 15; - packet_size_table[4][0x09f] = 12; - packet_size_table[4][0x0a2] = 120; - packet_size_table[4][0x0a7] = 11; -// packet_size_table[4][0x0f3] = -1; - packet_size_table[4][0x0f5] = 24; - packet_size_table[4][0x0f7] = 13; - packet_size_table[4][0x113] = 23; -// packet_size_table[4][0x116] = 2; - packet_size_table[4][0x190] = 26; - packet_size_table[4][0x193] = 18; - // new packet - packet_size_table[4][0x20f] = 10; - packet_size_table[4][0x210] = 22; - packet_size_table[4][0x212] = 26; - packet_size_table[4][0x213] = 26; - packet_size_table[4][0x214] = 42; - // size of packet version 10 - memcpy(&packet_size_table[5], &packet_size_table[4], sizeof(packet_len_table)); - packet_size_table[5][0x072] = 20; - packet_size_table[5][0x07e] = 19; - packet_size_table[5][0x085] = 23; - packet_size_table[5][0x089] = 9; - packet_size_table[5][0x08c] = 105; - packet_size_table[5][0x094] = 17; - packet_size_table[5][0x09b] = 14; - packet_size_table[5][0x09f] = -1; - packet_size_table[5][0x0a2] = 14; - packet_size_table[5][0x0a7] = 25; - packet_size_table[5][0x0f3] = 10; - packet_size_table[5][0x0f5] = 34; - packet_size_table[5][0x0f7] = 2; - packet_size_table[5][0x113] = 11; - packet_size_table[5][0x116] = 11; - packet_size_table[5][0x190] = 22; - packet_size_table[5][0x193] = 17; - // size of packet version 11 - memcpy(&packet_size_table[6], &packet_size_table[5], sizeof(packet_len_table)); - packet_size_table[6][0x072] = 18; - packet_size_table[6][0x07e] = 25; - packet_size_table[6][0x085] = 9; - packet_size_table[6][0x089] = 14; - packet_size_table[6][0x08c] = 109; - packet_size_table[6][0x094] = 19; - packet_size_table[6][0x09b] = 10; -// packet_size_table[6][0x09f] = -1; - packet_size_table[6][0x0a2] = 10; - packet_size_table[6][0x0a7] = 29; - packet_size_table[6][0x0f3] = 18; - packet_size_table[6][0x0f5] = 32; -// packet_size_table[6][0x0f7] = 2; - packet_size_table[6][0x113] = 14; - packet_size_table[6][0x116] = 14; - packet_size_table[6][0x190] = 14; - packet_size_table[6][0x193] = 12; - // size of packet version 12 - memcpy(&packet_size_table[7], &packet_size_table[6], sizeof(packet_len_table)); - packet_size_table[7][0x072] = 17; - packet_size_table[7][0x07e] = 16; -// packet_size_table[7][0x085] = 9; - packet_size_table[7][0x089] = 6; - packet_size_table[7][0x08c] = 103; - packet_size_table[7][0x094] = 14; - packet_size_table[7][0x09b] = 15; -// packet_size_table[7][0x09f] = -1; - packet_size_table[7][0x0a2] = 12; - packet_size_table[7][0x0a7] = 23; - packet_size_table[7][0x0f3] = 13; - packet_size_table[7][0x0f5] = 33; -// packet_size_table[7][0x0f7] = 2; - packet_size_table[7][0x113] = 10; - packet_size_table[7][0x116] = 10; - packet_size_table[7][0x190] = 20; - packet_size_table[7][0x193] = 26; - // size of packet version 13 - memcpy(&packet_size_table[8], &packet_size_table[7], sizeof(packet_len_table)); - packet_size_table[8][0x072] = 13; - packet_size_table[8][0x07e] = 13; - packet_size_table[8][0x085] = 15; -// packet_size_table[8][0x089] = 6; - packet_size_table[8][0x08c] = 108; - packet_size_table[8][0x094] = 12; - packet_size_table[8][0x09b] = 10; -// packet_size_table[8][0x09f] = -1; - packet_size_table[8][0x0a2] = 16; - packet_size_table[8][0x0a7] = 28; - packet_size_table[8][0x0f3] = 15; - packet_size_table[8][0x0f5] = 29; -// packet_size_table[8][0x0f7] = 2; - packet_size_table[8][0x113] = 9; - packet_size_table[8][0x116] = 9; - packet_size_table[8][0x190] = 26; - packet_size_table[8][0x193] = 22; + memcpy(packet_db[13], packet_db[12], sizeof(packet_db[0])); + // size of packet version 13 (25oct04) + packet_db[13][0x072].len = 13; + packet_db[13][0x07e].len = 13; + packet_db[13][0x085].len = 15; +// packet_db[13][0x089].len = 6; + packet_db[13][0x08c].len = 108; + packet_db[13][0x094].len = 12; + packet_db[13][0x09b].len = 10; +// packet_db[13][0x09f].len = -1; + packet_db[13][0x0a2].len = 16; + packet_db[13][0x0a7].len = 28; + packet_db[13][0x0f3].len = 15; + packet_db[13][0x0f5].len = 29; +// packet_db[13][0x0f7].len = 2; + packet_db[13][0x113].len = 9; + packet_db[13][0x116].len = 9; + packet_db[13][0x190].len = 26; + packet_db[13][0x193].len = 22; + // init packet function calls for packet ver 14 (same function of packet version 13, but size are different) + memcpy(packet_db[14], packet_db[13], sizeof(packet_db[0])); + // size of packet version 14 - Added by nsstrunks (1nov04) + packet_db[14][0x072].len = 13; + packet_db[14][0x07e].len = 13; + packet_db[14][0x085].len = 15; + packet_db[14][0x089].len = 6; + packet_db[14][0x08c].len = 108; + packet_db[14][0x094].len = 12; + packet_db[14][0x09b].len = 10; + packet_db[14][0x09f].len = -1; + packet_db[14][0x0a2].len = 16; + packet_db[14][0x0a7].len = 28; + packet_db[14][0x0f3].len = 15; + packet_db[14][0x0f5].len = 29; + packet_db[14][0x113].len = 9; + packet_db[14][0x116].len = 9; + packet_db[14][0x190].len = 26; + packet_db[14][0x193].len = 22; + packet_db[14][0x215].len = 6; + packet_db[14][0x216].len = 6; + packet_db[14][0x217].len = 2; + packet_db[14][0x218].len = 2; + packet_db[14][0x219].len = 282; + packet_db[14][0x21a].len = 282; + packet_db[14][0x21b].len = 10; + packet_db[14][0x21c].len = 10; +// packet_db[14][0x143].len = 23; // is this required? uncomment if it is + // Init packet function calls for packet ver 15 + memcpy(packet_db[15], packet_db[14], sizeof(packet_db[0])); + packet_db[15][0x072].func = clif_parse_UseSkillToId; + packet_db[15][0x07e].func = clif_parse_UseSkillToPos; + packet_db[15][0x089].func = clif_parse_TickSend; + packet_db[15][0x085].func = clif_parse_GlobalMessage; + packet_db[15][0x08c].func = clif_parse_GetCharNameRequest; + packet_db[15][0x094].func = clif_parse_MoveToKafra; + packet_db[15][0x09b].func = clif_parse_CloseKafra; + packet_db[15][0x09f].func = clif_parse_ActionRequest; + packet_db[15][0x0a2].func = clif_parse_TakeItem; + packet_db[15][0x0a7].func = clif_parse_WalkToXY; + packet_db[15][0x0f3].func = clif_parse_ChangeDir; + packet_db[15][0x0f5].func = clif_parse_WantToConnection; + packet_db[15][0x0f7].func = clif_parse_SolveCharName; + packet_db[15][0x113].func = clif_parse_UseSkillToPos; + packet_db[15][0x116].func = clif_parse_DropItem; + packet_db[15][0x190].func = clif_parse_UseItem; + packet_db[15][0x193].func = clif_parse_MoveFromKafra; + // Size of packet version 15 - Added by nsstrunks (6dec04) + packet_db[15][0x072].len = 22; + packet_db[15][0x07e].len = 30; + packet_db[15][0x094].len = 14; + packet_db[15][0x09f].len = 18; + packet_db[15][0x085].len = -1; + packet_db[15][0x08c].len = 13; + packet_db[15][0x089].len = 7; + packet_db[15][0x09b].len = 2; + packet_db[15][0x0a2].len = 7; + packet_db[15][0x0a7].len = 7; + packet_db[15][0x0f3].len = 8; + packet_db[15][0x0f5].len = 29; + packet_db[15][0x0f7].len = 14; + packet_db[15][0x113].len = 110; + packet_db[15][0x116].len = 12; + packet_db[15][0x190].len = 15; + packet_db[15][0x193].len = 21; + packet_db[15][0x21d].len = 6; + packet_db[15][0x222].len = 6; + packet_db[15][0x221].len = -1; + packet_db[15][0x223].len = 8; + // Init packet function calls for packet ver 16 + memcpy(packet_db[16], packet_db[15], sizeof(packet_db[0])); + packet_db[16][0x072].func = clif_parse_UseSkillToId; + packet_db[16][0x07e].func = clif_parse_UseSkillToPos; + packet_db[16][0x089].func = clif_parse_TickSend; + packet_db[16][0x0f3].func = clif_parse_GlobalMessage; + packet_db[16][0x08c].func = clif_parse_GetCharNameRequest; + packet_db[16][0x094].func = clif_parse_MoveToKafra; + packet_db[16][0x193].func = clif_parse_CloseKafra; + packet_db[16][0x190].func = clif_parse_ActionRequest; + packet_db[16][0x0f5].func = clif_parse_TakeItem; + packet_db[16][0x0a7].func = clif_parse_WalkToXY; + packet_db[16][0x085].func = clif_parse_ChangeDir; + packet_db[16][0x09b].func = clif_parse_WantToConnection; + packet_db[16][0x0a2].func = clif_parse_SolveCharName; + packet_db[16][0x113].func = clif_parse_UseSkillToPos; + packet_db[16][0x116].func = clif_parse_DropItem; + packet_db[16][0x09f].func = clif_parse_UseItem; + packet_db[16][0x0f7].func = clif_parse_MoveFromKafra; + // Size of packet version 16 [10jan05] + packet_db[16][0x072].len = 26; + packet_db[16][0x07e].len = 114; + packet_db[16][0x089].len = 9; + packet_db[16][0x0f3].len = -1; + packet_db[16][0x08c].len = 8; + packet_db[16][0x094].len = 20; + packet_db[16][0x193].len = 2; + packet_db[16][0x190].len = 20; + packet_db[16][0x0f5].len = 9; + packet_db[16][0x0a7].len = 13; + packet_db[16][0x085].len = 23; + packet_db[16][0x09b].len = 32; + packet_db[16][0x0a2].len = 11; + packet_db[16][0x113].len = 34; + packet_db[16][0x116].len = 20; + packet_db[16][0x09f].len = 17; + packet_db[16][0x0f7].len = 21; + packet_db[16][0x143].len = 10; + // Init packet function calls for the packet_db.txt (17) + memcpy(packet_db[MAX_PACKET_VER], packet_db[MAX_PACKET_VER - 1], sizeof(packet_db[0])); +#endif + + if (clif_config.enable_packet_db) + packetdb_readdb(); set_defaultparse(clif_parse); #ifdef __WIN32 - if (!make_listen_port(map_port)) { + //if (!make_listen_port(map_port)) { + if (!make_listen_bind(bind_ip,map_port)) { printf("cant bind game port\n"); exit(1); } #else for(i = 0; i < 10; i++) { - if (make_listen_port(map_port)) + //if (make_listen_port(map_port)) + if (make_listen_bind(bind_ip,map_port)) break; sleep(20); } diff --git a/src/map/clif.h b/src/map/clif.h index cf03820b1..b23eed5a6 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -13,7 +13,25 @@ typedef unsigned int in_addr_t; #include "map.h" +#define MAX_PACKET_DB 0x224 +#define MAX_PACKET_VER 17 + +struct packet_db { + short len; + void (*func)(int, struct map_session_data *); + short pos[20]; +}; +extern struct packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB]; + +extern struct Clif_Config { + int enable_packet_db; + int packet_db_ver; + int prefer_packet_db; + int connect_cmd; +} clif_config; + void clif_setip(char*); +void clif_setbindip(char*); void clif_setport(int); in_addr_t clif_getip(void); @@ -74,7 +92,7 @@ int clif_misceffect(struct block_list*,int); // area int clif_misceffect2(struct block_list *bl,int type); int clif_changeoption(struct block_list*); // area int clif_useitemack(struct map_session_data*,int,int,int); // self - +void clif_GlobalMessage(struct block_list *bl,char *message); int clif_createchat(struct map_session_data*,int); // self int clif_dispchat(struct chat_data*,int); // area or fd int clif_joinchatfail(struct map_session_data*,int); // self @@ -84,14 +102,17 @@ int clif_changechatowner(struct chat_data*,struct map_session_data*); // chat int clif_clearchat(struct chat_data*,int); // area or fd int clif_leavechat(struct chat_data*,struct map_session_data*); // chat int clif_changechatstatus(struct chat_data*); // chat +int clif_refresh(struct map_session_data*); // self void clif_emotion(struct block_list *bl,int type); void clif_talkiebox(struct block_list *bl,char* talkie); void clif_wedding_effect(struct block_list *bl); //void clif_sitting(int fd, struct map_session_data *sd); //void clif_callpartner(struct map_session_data *sd); +void clif_adopt_process(struct map_session_data *sd); void clif_sitting(struct map_session_data *sd); void clif_soundeffect(struct map_session_data *sd,struct block_list *bl,char *name,int type); +int clif_soundeffectall(struct block_list *bl, char *name, int type); // trade int clif_traderequest(struct map_session_data *sd,char *name); @@ -124,8 +145,8 @@ int clif_petinsight(struct block_list *bl,va_list ap); int clif_npcoutsight(struct block_list *bl,va_list ap); int clif_npcinsight(struct block_list *bl,va_list ap); -int clif_class_change(struct block_list *bl,int class,int type); -int clif_mob_class_change(struct mob_data *md,int class); +int clif_class_change(struct block_list *bl,int class_,int type); +int clif_mob_class_change(struct mob_data *md,int class_); int clif_mob_equip(struct mob_data *md,int nameid); // [Valaris] int clif_skillinfo(struct map_session_data *sd,int skillid,int type,int range); @@ -164,7 +185,7 @@ int clif_autospell(struct map_session_data *sd,int skilllv); int clif_devotion(struct map_session_data *sd,int target); int clif_spiritball(struct map_session_data *sd); int clif_combo_delay(struct block_list *src,int wait); -int clif_bladestop(struct block_list *src,struct block_list *dst,int bool); +int clif_bladestop(struct block_list *src,struct block_list *dst,int bool_); int clif_changemapcell(int m,int x,int y,int cell_type,int type); int clif_status_change(struct block_list *bl,int type,int flag); @@ -173,6 +194,7 @@ int clif_wis_message(int fd,char *nick,char *mes,int mes_len); int clif_wis_end(int fd,int flag); int clif_solved_charname(struct map_session_data *sd,int char_id); +int clif_update_mobhp(struct mob_data *md); int clif_use_card(struct map_session_data *sd,int idx); int clif_insert_card(struct map_session_data *sd,int idx_equip,int idx_card,int flag); @@ -195,6 +217,7 @@ int clif_item_skill(struct map_session_data *sd,int skillid,int skilllv,const ch int clif_mvp_effect(struct map_session_data *sd); int clif_mvp_item(struct map_session_data *sd,int nameid); int clif_mvp_exp(struct map_session_data *sd,int exp); +void clif_changed_dir(struct block_list *bl); // vending int clif_openvendingreq(struct map_session_data *sd,int num); @@ -218,6 +241,7 @@ int clif_party_message(struct party *p,int account_id,char *mes,int len); int clif_party_move(struct party *p,struct map_session_data *sd,int online); int clif_party_xy(struct party *p,struct map_session_data *sd); int clif_party_hp(struct party *p,struct map_session_data *sd); +int clif_hpmeter(struct map_session_data *sd); // guild int clif_guild_created(struct map_session_data *sd,int flag); @@ -277,6 +301,7 @@ int clif_message(struct block_list *bl, char* msg); // messages (from mobs/npcs) int clif_GM_kickack(struct map_session_data *sd,int id); int clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd,int type); +int clif_timedout(struct map_session_data *sd); int clif_foreachclient(int (*)(struct map_session_data*,va_list),...); diff --git a/src/map/guild.c b/src/map/guild.c index a48bb3020..935377e19 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -13,11 +13,13 @@ #include "battle.h" #include "npc.h" #include "pc.h" +#include "status.h" #include "map.h" #include "mob.h" #include "intif.h" #include "clif.h" #include "skill.h" +#include "showmsg.h" #ifdef MEMWATCH #include "memwatch.h" @@ -43,6 +45,14 @@ struct guild_expcache { int guild_id, account_id, char_id, exp; }; +// timer for auto saving guild data during WoE +#define GUILD_SAVE_INTERVAL 300000 +int guild_save_timer = -1; + +int guild_payexp_timer(int tid,unsigned int tick,int id,int data); +int guild_gvg_eliminate_timer(int tid,unsigned int tick,int id,int data); +int guild_save_sub(int tid,unsigned int tick,int id,int data); + // ƒMƒ‹ƒhƒXƒLƒ‹db‚̃AƒNƒZƒTi¡‚Í’¼‘Å‚¿‚Å‘ã—pj int guild_skill_get_inf(int id) { // Modified for new skills [Sara] if (id==GD_BATTLEORDER) return 4; @@ -54,9 +64,21 @@ int guild_skill_get_inf(int id) { // Modified for new skills [Sara] int guild_skill_get_sp(int id,int lv){ return 0; } int guild_skill_get_range(int id){ return 0; } int guild_skill_get_max(int id) { // Modified for new skills [Sara] - if(id==GD_EXTENSION) return 10; - else if(id==GD_REGENERATION) return 3; - else return 1; + switch (id) { + case GD_GUARDUP: + return 3; + case GD_EXTENSION: + return 10; + case GD_LEADERSHIP: + case GD_GLORYWOUNDS: + case GD_SOULCOLD: + case GD_HAWKEYES: + return 5; + case GD_REGENERATION: + return 3; + default: + return 1; + } } // ƒMƒ‹ƒhƒXƒLƒ‹‚ª‚ ‚é‚©Šm”F @@ -68,11 +90,6 @@ int guild_checkskill(struct guild *g,int id) return g->skill[idx].lv; } - -int guild_payexp_timer(int tid,unsigned int tick,int id,int data); -int guild_gvg_eliminate_timer(int tid,unsigned int tick,int id,int data); - - static int guild_read_castledb(void) { FILE *fp; @@ -115,7 +132,8 @@ static int guild_read_castledb(void) ln++; } fclose(fp); - printf("read db/castle_db.txt done (count=%d)\n",ln); + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/castle_db.txt"); + ShowStatus(tmp_output); return 0; } @@ -132,6 +150,7 @@ void do_init_guild(void) add_timer_func_list(guild_gvg_eliminate_timer,"guild_gvg_eliminate_timer"); add_timer_func_list(guild_payexp_timer,"guild_payexp_timer"); + add_timer_func_list(guild_save_sub, "guild_save_sub"); add_timer_interval(gettick()+GUILD_PAYEXP_INVERVAL,guild_payexp_timer,0,0,GUILD_PAYEXP_INVERVAL); } @@ -139,7 +158,7 @@ void do_init_guild(void) // ŒŸõ struct guild *guild_search(int guild_id) { - return numdb_search(guild_db,guild_id); + return (struct guild *) numdb_search(guild_db,guild_id); } int guild_searchname_sub(void *key,void *data,va_list ap) { @@ -160,7 +179,7 @@ struct guild* guild_searchname(char *str) } struct guild_castle *guild_castle_search(int gcid) { - return numdb_search(castle_db,gcid); + return (struct guild_castle *) numdb_search(castle_db,gcid); } // mapname‚ɑΉž‚µ‚½ƒAƒWƒg‚Ìgc‚ð•Ô‚· @@ -228,7 +247,7 @@ void guild_makemember(struct guild_member *m,struct map_session_data *sd) m->hair =sd->status.hair; m->hair_color =sd->status.hair_color; m->gender =sd->sex; - m->class =sd->status.class; + m->class_ =sd->status.class_; m->lv =sd->status.base_level; m->exp =0; m->exp_payper =0; @@ -270,7 +289,7 @@ int guild_payexp_timer_sub(void *key,void *data,va_list ap) c->exp=0; dellist[(*delp)++]=dataid; - free(c); + aFree(c); return 0; } int guild_payexp_timer(int tid,unsigned int tick,int id,int data) @@ -317,7 +336,7 @@ int guild_created(int account_id,int guild_id) struct guild *g; sd->status.guild_id=guild_id; sd->guild_sended=0; - if((g=numdb_search(guild_db,guild_id))!=NULL){ + if((g=(struct guild *) numdb_search(guild_db,guild_id))!=NULL){ printf("guild: id already exists!\n"); exit(1); } @@ -352,7 +371,7 @@ int guild_npc_request_info(int guild_id,const char *event) return guild_request_info(guild_id); ev=(struct eventlist *)aCalloc(1,sizeof(struct eventlist)); - memcpy(ev->name,event,sizeof(ev->name)); + memcpy(ev->name,event,strlen(event)); ev->next=(struct eventlist *)numdb_search(guild_infoevent_db,guild_id); numdb_insert(guild_infoevent_db,guild_id,ev); return guild_request_info(guild_id); @@ -367,7 +386,7 @@ int guild_check_member(const struct guild *g) nullpo_retr(0, g); for(i=0;i<fd_max;i++){ - if(session[i] && (sd=session[i]->session_data) && sd->state.auth){ + if(session[i] && (sd=(struct map_session_data *) session[i]->session_data) && sd->state.auth && !sd->state.waitingdisconnect){ if(sd->status.guild_id==g->guild_id){ int j,f=1; for(j=0;j<MAX_GUILD;j++){ // ƒf[ƒ^‚ª‚ ‚é‚© @@ -393,7 +412,7 @@ int guild_recv_noinfo(int guild_id) int i; struct map_session_data *sd; for(i=0;i<fd_max;i++){ - if(session[i] && (sd=session[i]->session_data) && sd->state.auth){ + if(session[i] && (sd=(struct map_session_data *) session[i]->session_data) && sd->state.auth && !sd->state.waitingdisconnect){ if(sd->status.guild_id==guild_id) sd->status.guild_id=0; } @@ -409,7 +428,7 @@ int guild_recv_info(struct guild *sg) nullpo_retr(0, sg); - if((g=numdb_search(guild_db,sg->guild_id))==NULL){ + if((g=(struct guild *) numdb_search(guild_db,sg->guild_id))==NULL){ g=(struct guild *)aCalloc(1,sizeof(struct guild)); numdb_insert(guild_db,sg->guild_id,g); before=*sg; @@ -423,9 +442,11 @@ int guild_recv_info(struct guild *sg) for(i=bm=m=0;i<g->max_member;i++){ // sd‚ÌÝ’è‚Æl”‚ÌŠm”F if(g->member[i].account_id>0){ struct map_session_data *sd = map_id2sd(g->member[i].account_id); - g->member[i].sd=(sd!=NULL && - sd->status.char_id==g->member[i].char_id && - sd->status.guild_id==g->guild_id)? sd:NULL; + if (sd && sd->status.char_id == g->member[i].char_id && + sd->status.guild_id == g->guild_id && + !sd->state.waitingdisconnect) + g->member[i].sd = sd; + else sd = NULL; m++; }else g->member[i].sd=NULL; @@ -460,10 +481,13 @@ int guild_recv_info(struct guild *sg) } // ƒCƒxƒ“ƒg‚Ì”¶ - if( (ev=numdb_search(guild_infoevent_db,sg->guild_id))!=NULL ){ + if( (ev=(struct eventlist *)numdb_search(guild_infoevent_db,sg->guild_id))!=NULL ){ numdb_erase(guild_infoevent_db,sg->guild_id); - for(;ev;ev2=ev->next,free(ev),ev=ev2){ + while(ev){ npc_event_do(ev->name); + ev2=ev->next; + aFree(ev); + ev=ev2; } } @@ -566,17 +590,18 @@ int guild_member_added(int guild_id,int account_id,int char_id,int flag) if( (g=guild_search(guild_id))==NULL ) return 0; - if((sd==NULL || sd->guild_invite==0) && flag==0){ + if(sd==NULL || sd->guild_invite==0){ // ƒLƒƒƒ‰‘¤‚É“o˜^‚Å‚«‚È‚©‚Á‚½‚½‚ß’E‘Þ—v‹‚ðo‚· - if(battle_config.error_log) - printf("guild: member added error %d is not online\n",account_id); - intif_guild_leave(guild_id,account_id,char_id,0,"**“o˜^ޏ”s**"); + if (flag == 0) { + if(battle_config.error_log) + printf("guild: member added error %d is not online\n",account_id); + intif_guild_leave(guild_id,account_id,char_id,0,"**“o˜^ޏ”s**"); + } return 0; } - sd->guild_invite=0; - sd->guild_invite_account=0; - - sd2=map_id2sd(sd->guild_invite_account); + sd2 = map_id2sd(sd->guild_invite_account); + sd->guild_invite = 0; + sd->guild_invite_account = 0; if(flag==1){ // ޏ”s if( sd2!=NULL ) @@ -659,11 +684,10 @@ int guild_member_leaved(int guild_id,int account_id,int char_id,int flag, { struct map_session_data *sd=map_id2sd(account_id); struct guild *g=guild_search(guild_id); - int i; if(g!=NULL){ int i; - for(i=0;i<g->max_member;i++) + for(i=0;i<g->max_member;i++) { if( g->member[i].account_id==account_id && g->member[i].char_id==char_id ){ struct map_session_data *sd2=sd; @@ -679,19 +703,21 @@ int guild_member_leaved(int guild_id,int account_id,int char_id,int flag, g->member[i].account_id=0; g->member[i].sd=NULL; } + // ƒƒ“ƒo[ƒŠƒXƒg‚ð‘Sˆõ‚ÉÄ’Ê’m + for(i=0;i<g->max_member;i++){ + if( g->member[i].sd!=NULL ) + clif_guild_memberlist(g->member[i].sd); + } + } } - if(sd!=NULL && sd->status.guild_id==guild_id){ - sd->status.guild_id=0; - sd->guild_emblem_id=0; - sd->guild_sended=0; - } - - // ƒƒ“ƒo[ƒŠƒXƒg‚ð‘Sˆõ‚ÉÄ’Ê’m - for(i=0;i<g->max_member;i++){ - if( g->member[i].sd!=NULL ) - clif_guild_memberlist(g->member[i].sd); + if(sd!=NULL) { + if (sd->status.guild_id==guild_id){ + sd->status.guild_id=0; + sd->guild_emblem_id=0; + sd->guild_sended=0; + } } - + return 0; } // ƒMƒ‹ƒhƒƒ“ƒo‚̃Iƒ“ƒ‰ƒCƒ“ó‘Ô/LvXV‘—M @@ -708,7 +734,7 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online) return 0; intif_guild_memberinfoshort(g->guild_id, - sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class); + sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class_); if( !online ){ // ƒƒOƒAƒEƒg‚·‚é‚È‚çsd‚ðƒNƒŠƒA‚µ‚ÄI—¹ int i=guild_getindex(g,sd->status.account_id,sd->status.char_id); @@ -736,7 +762,7 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online) return 0; } // ƒMƒ‹ƒhƒƒ“ƒo‚̃Iƒ“ƒ‰ƒCƒ“ó‘Ô/LvXV’Ê’m -int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class) +int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_) { int i,alv,c,idx=0,om=0,oldonline=-1; struct guild *g=guild_search(guild_id); @@ -748,7 +774,7 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin oldonline=m->online; m->online=online; m->lv=lv; - m->class=class; + m->class_=class_; idx=i; } if(m->account_id>0){ @@ -771,9 +797,11 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin for(i=0;i<g->max_member;i++){ // sdÄÝ’è struct map_session_data *sd= map_id2sd(g->member[i].account_id); - g->member[i].sd=(sd!=NULL && - sd->status.char_id==g->member[i].char_id && - sd->status.guild_id==guild_id)?sd:NULL; + if (sd && sd->status.char_id == g->member[i].char_id && + sd->status.guild_id == g->guild_id && + !sd->state.waitingdisconnect) + g->member[i].sd = sd; + else sd = NULL; } // ‚±‚±‚ɃNƒ‰ƒCƒAƒ“ƒg‚É‘—Mˆ—‚ª•K—v @@ -788,6 +816,8 @@ int guild_send_message(struct map_session_data *sd,char *mes,int len) if(sd->status.guild_id==0) return 0; intif_guild_message(sd->status.guild_id,sd->status.account_id,mes,len); + guild_recv_message(sd->status.guild_id,sd->status.account_id,mes,len); + return 0; } // ƒMƒ‹ƒh‰ï˜bŽóM @@ -870,14 +900,16 @@ int guild_notice_changed(int guild_id,const char *mes1,const char *mes2) // ƒMƒ‹ƒhƒGƒ“ƒuƒŒƒ€•ÏX int guild_change_emblem(struct map_session_data *sd,int len,const char *data) { + struct guild *g; nullpo_retr(0, sd); - struct guild *g = NULL; - if ((g = guild_search(sd->status.guild_id)) && guild_checkskill(g, GD_GLORYGUILD)>0) - return intif_guild_emblem(sd->status.guild_id,len,data); + if (battle_config.require_glory_guild && + !((g = guild_search(sd->status.guild_id)) && guild_checkskill(g, GD_GLORYGUILD)>0)) { + clif_skill_fail(sd,GD_GLORYGUILD,0,0); + return 0; + } - clif_skill_fail(sd,GD_GLORYGUILD,0,0); - return 0; + return intif_guild_emblem(sd->status.guild_id,len,data); } // ƒMƒ‹ƒhƒGƒ“ƒuƒŒƒ€•ÏX’Ê’m int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) @@ -920,8 +952,8 @@ int guild_payexp(struct map_session_data *sd,int exp) if( (exp2=exp*per/100)<=0 ) return 0; - if( (c=numdb_search(guild_expcache_db,sd->status.char_id))==NULL ){ - c=(struct guild_expcache *)aCalloc(1,sizeof(struct guild_expcache)); + if( (c=(struct guild_expcache *) numdb_search(guild_expcache_db,sd->status.char_id))==NULL ){ + c=(struct guild_expcache *)aCallocA(1,sizeof(struct guild_expcache)); c->guild_id=sd->status.guild_id; c->account_id=sd->status.account_id; c->char_id=sd->status.char_id; @@ -933,6 +965,30 @@ int guild_payexp(struct map_session_data *sd,int exp) return exp2; } +// Celest +int guild_getexp(struct map_session_data *sd,int exp) +{ + struct guild *g; + struct guild_expcache *c; + + nullpo_retr(0, sd); + + if(sd->status.guild_id==0 || (g=guild_search(sd->status.guild_id))==NULL ) + return 0; + + if( (c=(struct guild_expcache *) numdb_search(guild_expcache_db,sd->status.char_id))==NULL ){ + c=(struct guild_expcache *)aCallocA(1,sizeof(struct guild_expcache)); + c->guild_id=sd->status.guild_id; + c->account_id=sd->status.account_id; + c->char_id=sd->status.char_id; + c->exp=exp; + numdb_insert(guild_expcache_db,c->char_id,c); + }else{ + c->exp+=exp; + } + return exp; +} + // ƒXƒLƒ‹ƒ|ƒCƒ“ƒgŠ„‚èU‚è int guild_skillup(struct map_session_data *sd,int skill_num,int flag) { @@ -954,7 +1010,7 @@ int guild_skillup(struct map_session_data *sd,int skill_num,int flag) g->skill[idx].lv < guild_skill_get_max(skill_num) ){ intif_guild_skillup(g->guild_id,skill_num,sd->status.account_id,flag); } - pc_calcstatus (sd, 0); // Celest + status_calc_pc (sd, 0); // Celest return 0; } @@ -989,6 +1045,23 @@ int guild_get_alliance_count(struct guild *g,int flag) } return c; } +// “¯–¿ŠÖŒW‚©‚Ç‚¤‚©ƒ`ƒFƒbƒN +// “¯–¿‚È‚ç1A‚»‚êˆÈŠO‚Í0 +int guild_check_alliance(int guild_id1, int guild_id2, int flag) +{ + struct guild *g; + int i; + + g = guild_search(guild_id1); + if (g == NULL) + return 0; + + for (i=0; i<MAX_GUILDALLIANCE; i++) + if ((g->alliance[i].guild_id == guild_id2) && (g->alliance[i].opposition == flag)) + return 1; + + return 0; +} // ƒMƒ‹ƒh“¯–¿—v‹ int guild_reqalliance(struct map_session_data *sd,int account_id) { @@ -1146,11 +1219,18 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id int flag,const char *name1,const char *name2) { struct guild *g[2]; - int guild_id[2]={guild_id1,guild_id2}; - const char *guild_name[2]={name1,name2}; - struct map_session_data *sd[2]={map_id2sd(account_id1),map_id2sd(account_id2)}; + int guild_id[2]; + const char *guild_name[2]; + struct map_session_data *sd[2]; int j,i; + guild_id[0] = guild_id1; + guild_id[1] = guild_id2; + guild_name[0] = name1; + guild_name[1] = name2; + sd[0] = map_id2sd(account_id1); + sd[1] = map_id2sd(account_id2); + g[0]=guild_search(guild_id1); g[1]=guild_search(guild_id2); @@ -1252,7 +1332,7 @@ int guild_broken(int guild_id,int flag) numdb_foreach(guild_db,guild_broken_sub,guild_id); numdb_erase(guild_db,guild_id); guild_storage_delete(guild_id); - free(g); + aFree(g); return 0; } @@ -1301,7 +1381,7 @@ int guild_addcastleinfoevent(int castle_id,int index,const char *name) ev=(struct eventlist *)aCalloc(1,sizeof(struct eventlist)); memcpy(ev->name,name,sizeof(ev->name)); - ev->next=numdb_search(guild_castleinfoevent_db,code); + ev->next=(struct eventlist *) numdb_search(guild_castleinfoevent_db,code); numdb_insert(guild_castleinfoevent_db,code,ev); return 0; } @@ -1346,10 +1426,13 @@ int guild_castledataloadack(int castle_id,int index,int value) printf("guild_castledataloadack ERROR!! (Not found index=%d)\n", index); return 0; } - if( (ev=numdb_search(guild_castleinfoevent_db,code))!=NULL ){ + if( (ev=(struct eventlist *) numdb_search(guild_castleinfoevent_db,code))!=NULL ){ numdb_erase(guild_castleinfoevent_db,code); - for(;ev;ev2=ev->next,free(ev),ev=ev2){ + while(ev){ npc_event_do(ev->name); + ev2=ev->next; + aFree(ev); + ev=ev2; } } return 1; @@ -1439,6 +1522,8 @@ int guild_agit_start(void) { // Run All NPC_Event[OnAgitStart] int c = npc_event_doall("OnAgitStart"); printf("NPC_Event:[OnAgitStart] Run (%d) Events by @AgitStart.\n",c); + // Start auto saving + guild_save_timer = add_timer_interval (gettick() + GUILD_SAVE_INTERVAL, guild_save_sub, 0, 0, GUILD_SAVE_INTERVAL); return 0; } @@ -1446,20 +1531,82 @@ int guild_agit_end(void) { // Run All NPC_Event[OnAgitEnd] int c = npc_event_doall("OnAgitEnd"); printf("NPC_Event:[OnAgitEnd] Run (%d) Events by @AgitEnd.\n",c); + // Stop auto saving + delete_timer (guild_save_timer, guild_save_sub); return 0; } int guild_gvg_eliminate_timer(int tid,unsigned int tick,int id,int data) { // Run One NPC_Event[OnAgitEliminate] - size_t len = strlen((const char*)data); - char *evname=(char*)aCalloc(len + 4,sizeof(char)); + char *name = (char*)data; + size_t len = (name) ? strlen(name) : 0; + // the rest is dangerous, but let it crash, + // if this happens, it's ruined anyway + char *evname=(char*)aMalloc( (len + 4) * sizeof(char)); int c=0; - if(!agit_flag) return 0; // Agit already End - memcpy(evname,(const char *)data,len - 5); - strcpy(evname + len - 5,"Eliminate"); - c = npc_event_do(evname); - printf("NPC_Event:[%s] Run (%d) Events.\n",evname,c); + if(agit_flag) // Agit not already End + { + memcpy(evname,name,len - 5); + strcpy(evname + len - 5,"Eliminate"); + c = npc_event_do(evname); + printf("NPC_Event:[%s] Run (%d) Events.\n",evname,c); + } + if(name) aFree(name); + return 0; +} + +static int Ghp[MAX_GUILDCASTLE][8]; // so save only if HP are changed // experimental code [Yor] +static int Gid[MAX_GUILDCASTLE]; +int guild_save_sub(int tid,unsigned int tick,int id,int data) +{ + struct guild_castle *gc; + int i; + + for(i = 0; i < MAX_GUILDCASTLE; i++) { // [Yor] + gc = guild_castle_search(i); + if (!gc) continue; + if (gc->guild_id != Gid[i]) { + // Re-save guild id if its owner guild has changed + // This should already be done in gldfunc_ev_agit.txt, + // but since people have complained... Well x3 + guild_castledatasave(gc->castle_id, 1, gc->guild_id); + Gid[i] = gc->guild_id; + } + if (gc->visibleG0 == 1 && Ghp[i][0] != gc->Ghp0) { + guild_castledatasave(gc->castle_id, 18, gc->Ghp0); + Ghp[i][0] = gc->Ghp0; + } + if (gc->visibleG1 == 1 && Ghp[i][1] != gc->Ghp1) { + guild_castledatasave(gc->castle_id, 19, gc->Ghp1); + Ghp[i][1] = gc->Ghp1; + } + if (gc->visibleG2 == 1 && Ghp[i][2] != gc->Ghp2) { + guild_castledatasave(gc->castle_id, 20, gc->Ghp2); + Ghp[i][2] = gc->Ghp2; + } + if (gc->visibleG3 == 1 && Ghp[i][3] != gc->Ghp3) { + guild_castledatasave(gc->castle_id, 21, gc->Ghp3); + Ghp[i][3] = gc->Ghp3; + } + if (gc->visibleG4 == 1 && Ghp[i][4] != gc->Ghp4) { + guild_castledatasave(gc->castle_id, 22, gc->Ghp4); + Ghp[i][4] = gc->Ghp4; + } + if (gc->visibleG5 == 1 && Ghp[i][5] != gc->Ghp5) { + guild_castledatasave(gc->castle_id, 23, gc->Ghp5); + Ghp[i][5] = gc->Ghp5; + } + if (gc->visibleG6 == 1 && Ghp[i][6] != gc->Ghp6) { + guild_castledatasave(gc->castle_id, 24, gc->Ghp6); + Ghp[i][6] = gc->Ghp6; + } + if (gc->visibleG7 == 1 && Ghp[i][7] != gc->Ghp7) { + guild_castledatasave(gc->castle_id, 25, gc->Ghp7); + Ghp[i][7] = gc->Ghp7; + } + } + return 0; } @@ -1469,7 +1616,7 @@ int guild_agit_break(struct mob_data *md) nullpo_retr(0, md); - evname=(char *)aCalloc(strlen(md->npc_event) + 1, sizeof(char)); + evname=(char *)aCallocA(strlen(md->npc_event) + 1, sizeof(char)); strcpy(evname,md->npc_event); // Now By User to Run [OnAgitBreak] NPC Event... @@ -1491,7 +1638,7 @@ int guild_checkcastles(struct guild *g) { for(i=0;i<MAX_GUILDCASTLE;i++){ gc=guild_castle_search(i); cas_id=gc->guild_id; - if(g->guild_id==cas_id) + if(g->guild_id==cas_id) nb_cas=nb_cas+1; } //end for return nb_cas; @@ -1522,36 +1669,36 @@ int guild_isallied(struct guild *g, struct guild_castle *gc) return 0; } - + static int guild_db_final(void *key,void *data,va_list ap) { - struct guild *g=data; + struct guild *g=(struct guild *) data; - free(g); + aFree(g); return 0; } static int castle_db_final(void *key,void *data,va_list ap) { - struct guild_castle *gc=data; + struct guild_castle *gc=(struct guild_castle *) data; - free(gc); + aFree(gc); return 0; } static int guild_expcache_db_final(void *key,void *data,va_list ap) { - struct guild_expcache *c=data; + struct guild_expcache *c=(struct guild_expcache *) data; - free(c); + aFree(c); return 0; } static int guild_infoevent_db_final(void *key,void *data,va_list ap) { - struct eventlist *ev=data; + struct eventlist *ev=(struct eventlist *) data; - free(ev); + aFree(ev); return 0; } diff --git a/src/map/guild.h b/src/map/guild.h index 528605f7f..1dee350a1 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -29,6 +29,7 @@ struct map_session_data *guild_getavailablesd(struct guild *g); int guild_getindex(struct guild *g,int account_id,int char_id); int guild_getposition(struct map_session_data *sd,struct guild *g); int guild_payexp(struct map_session_data *sd,int exp); +int guild_getexp(struct map_session_data *sd,int exp); // [Celest] int guild_create(struct map_session_data *sd,char *name); int guild_created(int account_id,int guild_id); @@ -53,9 +54,10 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id int flag,const char *name1,const char *name2); int guild_delalliance(struct map_session_data *sd,int guild_id,int flag); int guild_opposition(struct map_session_data *sd,int char_id); +int guild_check_alliance(int guild_id1, int guild_id2, int flag); int guild_send_memberinfoshort(struct map_session_data *sd,int online); -int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class); +int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_); int guild_change_memberposition(int guild_id,int account_id,int char_id,int idx); int guild_memberposition_changed(struct guild *g,int idx,int pos); int guild_change_position(struct map_session_data *sd,int idx, diff --git a/src/map/intif.c b/src/map/intif.c index fc79e5148..3aa472ad8 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -31,6 +31,7 @@ #include "guild.h" #include "pet.h" #include "nullpo.h" +#include "malloc.h" #ifdef MEMWATCH #include "memwatch.h" @@ -54,10 +55,16 @@ extern int char_fd; // inter server‚Ìfd‚Íchar_fd‚ðŽg‚¤ //----------------------------------------------------------------- // inter server‚Ö‚Ì‘—M +int CheckForCharServer() { + return ((char_fd == -1) || session[char_fd] == NULL || session[char_fd]->wdata == NULL); +} + // pet int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,short pet_egg_id, short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3080; WFIFOL(inter_fd,2) = account_id; WFIFOL(inter_fd,6) = char_id; @@ -77,6 +84,8 @@ int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,sho int intif_request_petdata(int account_id,int char_id,int pet_id) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3081; WFIFOL(inter_fd,2) = account_id; WFIFOL(inter_fd,6) = char_id; @@ -88,6 +97,8 @@ int intif_request_petdata(int account_id,int char_id,int pet_id) int intif_save_petdata(int account_id,struct s_pet *p) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3082; WFIFOW(inter_fd,2) = sizeof(struct s_pet) + 8; WFIFOL(inter_fd,4) = account_id; @@ -99,6 +110,8 @@ int intif_save_petdata(int account_id,struct s_pet *p) int intif_delete_petdata(int pet_id) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3083; WFIFOL(inter_fd,2) = pet_id; WFIFOSET(inter_fd,6); @@ -110,18 +123,25 @@ int intif_delete_petdata(int pet_id) int intif_GMmessage(char* mes,int len,int flag) { int lp = (flag&0x10) ? 8 : 4; + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3000; WFIFOW(inter_fd,2) = lp + len; WFIFOL(inter_fd,4) = 0x65756c62; memcpy(WFIFOP(inter_fd,lp), mes, len); WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + // Send to the local players + clif_GMmessage(NULL, mes, len, 0); + return 0; } // The transmission of Wisp/Page to inter-server (player not found on this server) int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, int mes_len) { nullpo_retr(0, sd); + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3001; WFIFOW(inter_fd,2) = mes_len + 52; @@ -138,6 +158,8 @@ int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, int me // The reply of Wisp/page int intif_wis_replay(int id, int flag) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3002; WFIFOL(inter_fd,2) = id; WFIFOB(inter_fd,6) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target @@ -150,7 +172,11 @@ int intif_wis_replay(int id, int flag) { } // The transmission of GM only Wisp/Page from server to inter-server -int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes, int mes_len) { +int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes) { + int mes_len; + if (CheckForCharServer()) + return 0; + mes_len = strlen(mes) + 1; // + null WFIFOW(inter_fd,0) = 0x3003; WFIFOW(inter_fd,2) = mes_len + 30; memcpy(WFIFOP(inter_fd,4), Wisp_name, 24); @@ -167,9 +193,14 @@ int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes, int me // ƒAƒJƒEƒ“ƒg•Ï”‘—M int intif_saveaccountreg(struct map_session_data *sd) { int j,p; + if (CheckForCharServer()) + return 0; nullpo_retr(0, sd); + if (sd->status.account_reg_num == -1) + return 0; + WFIFOW(inter_fd,0) = 0x3004; WFIFOL(inter_fd,4) = sd->bl.id; for(j=0,p=8;j<sd->status.account_reg_num;j++,p+=36){ @@ -184,16 +215,23 @@ int intif_saveaccountreg(struct map_session_data *sd) { int intif_request_accountreg(struct map_session_data *sd) { nullpo_retr(0, sd); + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3005; WFIFOL(inter_fd,2) = sd->bl.id; WFIFOSET(inter_fd,6); + + sd->status.account_reg_num = -1; + return 0; } // ‘qŒÉƒf[ƒ^—v‹ int intif_request_storage(int account_id) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3010; WFIFOL(inter_fd,2) = account_id; WFIFOSET(inter_fd,6); @@ -202,6 +240,8 @@ int intif_request_storage(int account_id) // ‘qŒÉƒf[ƒ^‘—M int intif_send_storage(struct storage *stor) { + if (CheckForCharServer()) + return 0; nullpo_retr(0, stor); WFIFOW(inter_fd,0) = 0x3011; WFIFOW(inter_fd,2) = sizeof(struct storage)+8; @@ -213,6 +253,8 @@ int intif_send_storage(struct storage *stor) int intif_request_guild_storage(int account_id,int guild_id) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3018; WFIFOL(inter_fd,2) = account_id; WFIFOL(inter_fd,6) = guild_id; @@ -221,6 +263,8 @@ int intif_request_guild_storage(int account_id,int guild_id) } int intif_send_guild_storage(int account_id,struct guild_storage *gstor) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3019; WFIFOW(inter_fd,2) = sizeof(struct guild_storage)+12; WFIFOL(inter_fd,4) = account_id; @@ -231,8 +275,10 @@ int intif_send_guild_storage(int account_id,struct guild_storage *gstor) } // ƒp[ƒeƒB쬗v‹ -int intif_create_party(struct map_session_data *sd,char *name) +int intif_create_party(struct map_session_data *sd,char *name,int item,int item2) { + if (CheckForCharServer()) + return 0; nullpo_retr(0, sd); WFIFOW(inter_fd,0) = 0x3020; @@ -241,7 +287,9 @@ int intif_create_party(struct map_session_data *sd,char *name) memcpy(WFIFOP(inter_fd,30),sd->status.name,24); memcpy(WFIFOP(inter_fd,54),map[sd->bl.m].name,16); WFIFOW(inter_fd,70)= sd->status.base_level; - WFIFOSET(inter_fd,72); + WFIFOB(inter_fd,72)= item; + WFIFOB(inter_fd,73)= item2; + WFIFOSET(inter_fd,74); // if(battle_config.etc_log) // printf("intif: create party\n"); return 0; @@ -249,6 +297,8 @@ int intif_create_party(struct map_session_data *sd,char *name) // ƒp[ƒeƒBî•ñ—v‹ int intif_request_partyinfo(int party_id) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3021; WFIFOL(inter_fd,2) = party_id; WFIFOSET(inter_fd,6); @@ -260,6 +310,8 @@ int intif_request_partyinfo(int party_id) int intif_party_addmember(int party_id,int account_id) { struct map_session_data *sd; + if (CheckForCharServer()) + return 0; sd=map_id2sd(account_id); // if(battle_config.etc_log) // printf("intif: party add member %d %d\n",party_id,account_id); @@ -277,6 +329,8 @@ int intif_party_addmember(int party_id,int account_id) // ƒp[ƒeƒBÝ’è•ÏX int intif_party_changeoption(int party_id,int account_id,int exp,int item) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0)=0x3023; WFIFOL(inter_fd,2)=party_id; WFIFOL(inter_fd,6)=account_id; @@ -288,6 +342,8 @@ int intif_party_changeoption(int party_id,int account_id,int exp,int item) // ƒp[ƒeƒB’E‘Þ—v‹ int intif_party_leave(int party_id,int account_id) { + if (CheckForCharServer()) + return 0; // if(battle_config.etc_log) // printf("intif: party leave %d %d\n",party_id,account_id); WFIFOW(inter_fd,0)=0x3024; @@ -299,6 +355,8 @@ int intif_party_leave(int party_id,int account_id) // ƒp[ƒeƒBˆÚ“®—v‹ int intif_party_changemap(struct map_session_data *sd,int online) { + if (CheckForCharServer()) + return 0; if(sd!=NULL){ WFIFOW(inter_fd,0)=0x3025; WFIFOL(inter_fd,2)=sd->status.party_id; @@ -315,6 +373,8 @@ int intif_party_changemap(struct map_session_data *sd,int online) // ƒp[ƒeƒB[‰ðŽU—v‹ int intif_break_party(int party_id) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0)=0x3026; WFIFOL(inter_fd,2)=party_id; WFIFOSET(inter_fd,6); @@ -323,6 +383,8 @@ int intif_break_party(int party_id) // ƒp[ƒeƒB‰ï˜b‘—M int intif_party_message(int party_id,int account_id,char *mes,int len) { + if (CheckForCharServer()) + return 0; // if(battle_config.etc_log) // printf("intif_party_message: %s\n",mes); WFIFOW(inter_fd,0)=0x3027; @@ -336,6 +398,8 @@ int intif_party_message(int party_id,int account_id,char *mes,int len) // ƒp[ƒeƒB‹£‡ƒ`ƒFƒbƒN—v‹ int intif_party_checkconflict(int party_id,int account_id,char *nick) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0)=0x3028; WFIFOL(inter_fd,2)=party_id; WFIFOL(inter_fd,6)=account_id; @@ -347,6 +411,8 @@ int intif_party_checkconflict(int party_id,int account_id,char *nick) // ƒMƒ‹ƒh쬗v‹ int intif_guild_create(const char *name,const struct guild_member *master) { + if (CheckForCharServer()) + return 0; nullpo_retr(0, master); WFIFOW(inter_fd,0)=0x3030; @@ -360,6 +426,8 @@ int intif_guild_create(const char *name,const struct guild_member *master) // ƒMƒ‹ƒhî•ñ—v‹ int intif_guild_request_info(int guild_id) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3031; WFIFOL(inter_fd,2) = guild_id; WFIFOSET(inter_fd,6); @@ -368,6 +436,8 @@ int intif_guild_request_info(int guild_id) // ƒMƒ‹ƒhƒƒ“ƒo’ljÁ—v‹ int intif_guild_addmember(int guild_id,struct guild_member *m) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0) = 0x3032; WFIFOW(inter_fd,2) = sizeof(struct guild_member)+8; WFIFOL(inter_fd,4) = guild_id; @@ -378,6 +448,8 @@ int intif_guild_addmember(int guild_id,struct guild_member *m) // ƒMƒ‹ƒhƒƒ“ƒo’E‘Þ/’Ç•ú—v‹ int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const char *mes) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd, 0) = 0x3034; WFIFOL(inter_fd, 2) = guild_id; WFIFOL(inter_fd, 6) = account_id; @@ -389,21 +461,25 @@ int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const cha } // ƒMƒ‹ƒhƒƒ“ƒo‚̃Iƒ“ƒ‰ƒCƒ“ó‹µ/LvXV—v‹ int intif_guild_memberinfoshort(int guild_id, - int account_id,int char_id,int online,int lv,int class) + int account_id,int char_id,int online,int lv,int class_) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd, 0) = 0x3035; WFIFOL(inter_fd, 2) = guild_id; WFIFOL(inter_fd, 6) = account_id; WFIFOL(inter_fd,10) = char_id; WFIFOB(inter_fd,14) = online; WFIFOW(inter_fd,15) = lv; - WFIFOW(inter_fd,17) = class; + WFIFOW(inter_fd,17) = class_; WFIFOSET(inter_fd,19); return 0; } // ƒMƒ‹ƒh‰ðŽU’Ê’m int intif_guild_break(int guild_id) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd, 0) = 0x3036; WFIFOL(inter_fd, 2) = guild_id; WFIFOSET(inter_fd,6); @@ -412,17 +488,22 @@ int intif_guild_break(int guild_id) // ƒMƒ‹ƒh‰ï˜b‘—M int intif_guild_message(int guild_id,int account_id,char *mes,int len) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0)=0x3037; WFIFOW(inter_fd,2)=len+12; WFIFOL(inter_fd,4)=guild_id; WFIFOL(inter_fd,8)=account_id; memcpy(WFIFOP(inter_fd,12),mes,len); WFIFOSET(inter_fd,len+12); + return 0; } // ƒMƒ‹ƒh‹£‡ƒ`ƒFƒbƒN—v‹ int intif_guild_checkconflict(int guild_id,int account_id,int char_id) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd, 0)=0x3038; WFIFOL(inter_fd, 2)=guild_id; WFIFOL(inter_fd, 6)=account_id; @@ -433,6 +514,8 @@ int intif_guild_checkconflict(int guild_id,int account_id,int char_id) // ƒMƒ‹ƒhŠî–{î•ñ•ÏX—v‹ int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0)=0x3039; WFIFOW(inter_fd,2)=len+10; WFIFOL(inter_fd,4)=guild_id; @@ -445,6 +528,8 @@ int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len) int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id, int type,const void *data,int len) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd, 0)=0x303a; WFIFOW(inter_fd, 2)=len+18; WFIFOL(inter_fd, 4)=guild_id; @@ -458,6 +543,8 @@ int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id, // ƒMƒ‹ƒh–ðE•ÏX—v‹ int intif_guild_position(int guild_id,int idx,struct guild_position *p) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0)=0x303b; WFIFOW(inter_fd,2)=sizeof(struct guild_position)+12; WFIFOL(inter_fd,4)=guild_id; @@ -469,6 +556,8 @@ int intif_guild_position(int guild_id,int idx,struct guild_position *p) // ƒMƒ‹ƒhƒXƒLƒ‹ƒAƒbƒv—v‹ int intif_guild_skillup(int guild_id,int skill_num,int account_id,int flag) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd, 0)=0x303c; WFIFOL(inter_fd, 2)=guild_id; WFIFOL(inter_fd, 6)=skill_num; @@ -480,6 +569,8 @@ int intif_guild_skillup(int guild_id,int skill_num,int account_id,int flag) // ƒMƒ‹ƒh“¯–¿/“G‘Ηv‹ int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd, 0)=0x303d; WFIFOL(inter_fd, 2)=guild_id1; WFIFOL(inter_fd, 6)=guild_id2; @@ -492,6 +583,8 @@ int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account // ƒMƒ‹ƒh’m•ÏX—v‹ int intif_guild_notice(int guild_id,const char *mes1,const char *mes2) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0)=0x303e; WFIFOL(inter_fd,2)=guild_id; memcpy(WFIFOP(inter_fd,6),mes1,60); @@ -502,6 +595,8 @@ int intif_guild_notice(int guild_id,const char *mes1,const char *mes2) // ƒMƒ‹ƒhƒGƒ“ƒuƒŒƒ€•ÏX—v‹ int intif_guild_emblem(int guild_id,int len,const char *data) { + if (CheckForCharServer()) + return 0; if(guild_id<=0 || len<0 || len>2000) return 0; WFIFOW(inter_fd,0)=0x303f; @@ -515,6 +610,8 @@ int intif_guild_emblem(int guild_id,int len,const char *data) //Œ»Ý‚̃Mƒ‹ƒhéè—̃Mƒ‹ƒh‚𒲂ׂé int intif_guild_castle_dataload(int castle_id,int index) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0)=0x3040; WFIFOW(inter_fd,2)=castle_id; WFIFOB(inter_fd,4)=index; @@ -525,6 +622,8 @@ int intif_guild_castle_dataload(int castle_id,int index) //ƒMƒ‹ƒhéè—̃Mƒ‹ƒh•ÏX—v‹ int intif_guild_castle_datasave(int castle_id,int index, int value) { + if (CheckForCharServer()) + return 0; WFIFOW(inter_fd,0)=0x3041; WFIFOW(inter_fd,2)=castle_id; WFIFOB(inter_fd,4)=index; @@ -539,14 +638,15 @@ int intif_guild_castle_datasave(int castle_id,int index, int value) // Wisp/Page reception int intif_parse_WisMessage(int fd) { // rewritten by [Yor] struct map_session_data* sd; + char *wisp_source; int id=RFIFOL(fd,4); int i=0; //,j=0; // if(battle_config.etc_log) // printf("intif_parse_wismessage: %d %s %s %s\n",id,RFIFOP(fd,6),RFIFOP(fd,30),RFIFOP(fd,54) ); - - sd=map_nick2sd(RFIFOP(fd,32)); // ‘—Mæ‚ð’T‚· - if(sd!=NULL && strcmp(sd->status.name, RFIFOP(fd,32)) == 0){ + + sd=(struct map_session_data *) map_nick2sd((char *) RFIFOP(fd,32)); // ‘—Mæ‚ð’T‚· + if(sd!=NULL && strcmp((char *) sd->status.name, (char *) RFIFOP(fd,32)) == 0){ /* for(i=0;i<MAX_WIS_REFUSAL;i++){ //‹‘”ÛƒŠƒXƒg‚É–¼‘O‚ª‚ ‚é‚©‚Ç‚¤‚©”»’肵‚Ä‚ ‚ê‚΋‘”Û if(strcmp(sd->wis_refusal[i],RFIFOP(fd,8))==0){ @@ -563,9 +663,20 @@ int intif_parse_WisMessage(int fd) { // rewritten by [Yor] else{ */ - if(i == MAX_IGNORE_LIST) { - clif_wis_message(sd->fd,RFIFOP(fd,8),RFIFOP(fd,56),RFIFOW(fd,2)-56); - intif_wis_replay(RFIFOL(fd,4),0); // ‘—M¬Œ÷ + else { + wisp_source = (char *) RFIFOP(fd,8); // speed up [Yor] + for(i=0;i<MAX_IGNORE_LIST;i++){ //‹‘”ÛƒŠƒXƒg‚É–¼‘O‚ª‚ ‚é‚©‚Ç‚¤‚©”»’肵‚Ä‚ ‚ê‚΋‘”Û + if(strcmp(sd->ignore[i].name, wisp_source)==0){ + break; + } + } + if(i==MAX_IGNORE_LIST) // run out of list, so we are not ignored + { + clif_wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56); + intif_wis_replay(id,0); // ‘—M¬Œ÷ + } + else + intif_wis_replay(id, 2); // ŽóM‹‘”Û } }else intif_wis_replay(id,1); // ‚»‚ñ‚Èl‚¢‚Ü‚¹‚ñ @@ -578,7 +689,7 @@ int intif_parse_WisEnd(int fd) { if (battle_config.etc_log) printf("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - sd = map_nick2sd(RFIFOP(fd,2)); + sd = (struct map_session_data *)map_nick2sd((char *) RFIFOP(fd,2)); if (sd != NULL) clif_wis_end(sd->fd, RFIFOB(fd,26)); @@ -591,7 +702,7 @@ int mapif_parse_WisToGM(int fd) { // 0x3003/0x3803 <packet_len>.w <wispname>.24B struct map_session_data *pl_sd; char Wisp_name[24]; char mbuf[255]; - char *message = ((RFIFOW(fd,2) - 30) >= sizeof(mbuf)) ? (char *) malloc((RFIFOW(fd,2) - 30)) : mbuf; + char *message = (char *) (((RFIFOW(fd,2) - 30) >= sizeof(mbuf)) ? (char *) aMallocA((RFIFOW(fd,2) - 30)) : mbuf); min_gm_level = (int)RFIFOW(fd,28); memcpy(Wisp_name, RFIFOP(fd,4), 24); @@ -600,12 +711,12 @@ int mapif_parse_WisToGM(int fd) { // 0x3003/0x3803 <packet_len>.w <wispname>.24B message[sizeof(message) - 1] = '\0'; // information is sended to all online GM for (i = 0; i < fd_max; i++) - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) if (pc_isGM(pl_sd) >= min_gm_level) clif_wis_message(i, Wisp_name, message, strlen(message) + 1); if (message != mbuf) - free(message); + aFree(message); return 0; } @@ -633,6 +744,13 @@ int intif_parse_LoadStorage(int fd) { struct map_session_data *sd; stor = account2storage( RFIFOL(fd,4)); + + if (stor->storage_status == 1) { // Already open.. lets ignore this update + if (battle_config.error_log) + printf("intif_parse_LoadStorage: storage received for a client already open\n"); + return 0; + } + if (RFIFOW(fd,2)-8 != sizeof(struct storage)) { if (battle_config.error_log) printf("intif_parse_LoadStorage: data size error %d %d\n", RFIFOW(fd,2)-8, sizeof(struct storage)); @@ -647,6 +765,7 @@ int intif_parse_LoadStorage(int fd) { if(battle_config.save_log) printf("intif_openstorage: %d\n",RFIFOL(fd,4) ); memcpy(stor,RFIFOP(fd,8),sizeof(struct storage)); + stor->dirty=0; stor->storage_status=1; sd->state.storage_flag = 0; clif_storageitemlist(sd,stor); @@ -712,7 +831,7 @@ int intif_parse_PartyCreated(int fd) { if(battle_config.etc_log) printf("intif: party created\n"); - party_created(RFIFOL(fd,2),RFIFOB(fd,6),RFIFOL(fd,7),RFIFOP(fd,11)); + party_created(RFIFOL(fd,2), RFIFOB(fd,6),RFIFOL(fd,7),(char *) RFIFOP(fd,11)); return 0; } // ƒp[ƒeƒBî•ñ @@ -752,7 +871,7 @@ int intif_parse_PartyMemberLeaved(int fd) { if(battle_config.etc_log) printf("intif: party member leaved %d %d %s\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10)); - party_member_leaved(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10)); + party_member_leaved(RFIFOL(fd,2),RFIFOL(fd,6),(char *) RFIFOP(fd,10)); return 0; } // ƒp[ƒeƒB‰ðŽU’Ê’m @@ -766,7 +885,7 @@ int intif_parse_PartyMove(int fd) { // if(battle_config.etc_log) // printf("intif: party move %d %d %s %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27)); - party_recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27)); + party_recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),(char *) RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27)); return 0; } // ƒp[ƒeƒBƒƒbƒZ[ƒW @@ -774,7 +893,7 @@ int intif_parse_PartyMessage(int fd) { // if(battle_config.etc_log) // printf("intif_parse_PartyMessage: %s\n",RFIFOP(fd,12)); - party_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),RFIFOP(fd,12),RFIFOW(fd,2)-12); + party_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); return 0; } @@ -815,7 +934,7 @@ int intif_parse_GuildMemberAdded(int fd) int intif_parse_GuildMemberLeaved(int fd) { guild_member_leaved(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14), - RFIFOP(fd,55),RFIFOP(fd,15)); + (char *) RFIFOP(fd,55), (char *) RFIFOP(fd,15)); return 0; } @@ -892,25 +1011,25 @@ int intif_parse_GuildSkillUp(int fd) int intif_parse_GuildAlliance(int fd) { guild_allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14), - RFIFOB(fd,18),RFIFOP(fd,19),RFIFOP(fd,43)); + RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43)); return 0; } // ƒMƒ‹ƒh’m•ÏX’Ê’m int intif_parse_GuildNotice(int fd) { - guild_notice_changed(RFIFOL(fd,2),RFIFOP(fd,6),RFIFOP(fd,66)); + guild_notice_changed(RFIFOL(fd,2),(char *) RFIFOP(fd,6),(char *) RFIFOP(fd,66)); return 0; } // ƒMƒ‹ƒhƒGƒ“ƒuƒŒƒ€•ÏX’Ê’m int intif_parse_GuildEmblem(int fd) { - guild_emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8),RFIFOP(fd,12)); + guild_emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8), (char *)RFIFOP(fd,12)); return 0; } // ƒMƒ‹ƒh‰ï˜bŽóM int intif_parse_GuildMessage(int fd) { - guild_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),RFIFOP(fd,12),RFIFOW(fd,2)-12); + guild_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); return 0; } // ƒMƒ‹ƒhéƒf[ƒ^—v‹•ÔM @@ -999,7 +1118,7 @@ int intif_parse(int fd) } // ˆ—•ªŠò switch(cmd){ - case 0x3800: clif_GMmessage(NULL,RFIFOP(fd,4),packet_len-4,0); break; + case 0x3800: clif_GMmessage(NULL,(char *) RFIFOP(fd,4),packet_len-4,0); break; case 0x3801: intif_parse_WisMessage(fd); break; case 0x3802: intif_parse_WisEnd(fd); break; case 0x3803: mapif_parse_WisToGM(fd); break; diff --git a/src/map/intif.h b/src/map/intif.h index 5077dbe18..17d6045ac 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -7,7 +7,7 @@ int intif_parse(int fd); int intif_GMmessage(char* mes,int len,int flag); int intif_wis_message(struct map_session_data *sd,char *nick,char *mes,int mes_len); -int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes, int mes_len); +int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes); int intif_saveaccountreg(struct map_session_data *sd); int intif_request_accountreg(struct map_session_data *sd); @@ -18,7 +18,7 @@ int intif_request_guild_storage(int account_id, int guild_id); int intif_send_guild_storage(int account_id, struct guild_storage *gstor); -int intif_create_party(struct map_session_data *sd,char *name); +int intif_create_party(struct map_session_data *sd,char *name,int item,int item2); int intif_request_partyinfo(int party_id); int intif_party_addmember(int party_id, int account_id); int intif_party_changeoption(int party_id, int account_id, int exp, int item); @@ -33,7 +33,7 @@ int intif_guild_create(const char *name, const struct guild_member *master); int intif_guild_request_info(int guild_id); int intif_guild_addmember(int guild_id, struct guild_member *m); int intif_guild_leave(int guild_id, int account_id, int char_id, int flag, const char *mes); -int intif_guild_memberinfoshort(int guild_id, int account_id, int char_id, int online, int lv, int class); +int intif_guild_memberinfoshort(int guild_id, int account_id, int char_id, int online, int lv, int class_); int intif_guild_break(int guild_id); int intif_guild_message(int guild_id, int account_id, char *mes, int len); int intif_guild_checkconflict(int guild_id, int account_id, int char_id); diff --git a/src/map/itemdb.c b/src/map/itemdb.c index a225cff83..91ec58c81 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -12,6 +12,7 @@ #include "itemdb.h" #include "script.h" #include "pc.h" +#include "showmsg.h" #ifdef MEMWATCH #include "memwatch.h" @@ -25,9 +26,9 @@ static struct dbt* item_db; -static struct random_item_data blue_box[MAX_RANDITEM],violet_box[MAX_RANDITEM],card_album[MAX_RANDITEM],gift_box[MAX_RANDITEM],scroll[MAX_RANDITEM]; -static int blue_box_count=0,violet_box_count=0,card_album_count=0,gift_box_count=0,scroll_count=0; -static int blue_box_default=0,violet_box_default=0,card_album_default=0,gift_box_default=0,scroll_default=0; +static struct random_item_data blue_box[MAX_RANDITEM], violet_box[MAX_RANDITEM], card_album[MAX_RANDITEM], gift_box[MAX_RANDITEM], scroll[MAX_RANDITEM], finding_ore[MAX_RANDITEM]; +static int blue_box_count=0, violet_box_count=0, card_album_count=0, gift_box_count=0, scroll_count=0, finding_ore_count = 0; +static int blue_box_default=0, violet_box_default=0, card_album_default=0, gift_box_default=0, scroll_default=0, finding_ore_default = 0; // Function declarations @@ -39,7 +40,11 @@ static int itemdb_read_sqldb(void); static int itemdb_read_randomitem(); static int itemdb_read_itemavail(void); static int itemdb_read_itemnametable(void); +static int itemdb_read_itemslottable(void); +static int itemdb_read_itemslotcounttable(void); +static int itemdb_read_cardillustnametable(void); static int itemdb_read_noequip(void); +static int itemdb_read_norefine(void); void itemdb_reload(void); /*========================================== @@ -97,16 +102,18 @@ int itemdb_searchrandomid(int flags) struct { int nameid,count; struct random_item_data *list; - } data[] ={ - { 0,0,NULL }, - { blue_box_default ,blue_box_count ,blue_box }, - { violet_box_default,violet_box_count ,violet_box }, - { card_album_default,card_album_count ,card_album }, - { gift_box_default ,gift_box_count ,gift_box }, - { scroll_default ,scroll_count ,scroll }, - }; - - if(flags>=1 && flags<=5){ + } data[7]; + + // for BCC32 compile error + data[0].nameid = 0; data[0].count = 0; data[0].list = NULL; + data[1].nameid = blue_box_default; data[1].count = blue_box_count; data[1].list = blue_box; + data[2].nameid = violet_box_default; data[2].count = violet_box_count; data[2].list = violet_box; + data[3].nameid = card_album_default; data[3].count = card_album_count; data[3].list = card_album; + data[4].nameid = gift_box_default; data[4].count = gift_box_count; data[4].list = gift_box; + data[5].nameid = scroll_default; data[5].count = scroll_count; data[5].list = scroll; + data[6].nameid = finding_ore_default; data[6].count = finding_ore_count; data[6].list = finding_ore; + + if(flags>=1 && flags<=6){ nameid=data[flags].nameid; count=data[flags].count; list=data[flags].list; @@ -130,7 +137,7 @@ int itemdb_searchrandomid(int flags) */ struct item_data* itemdb_exists(int nameid) { - return numdb_search(item_db,nameid); + return (struct item_data *) numdb_search(item_db,nameid); } /*========================================== * DB‚ÌŒŸõ @@ -140,7 +147,7 @@ struct item_data* itemdb_search(int nameid) { struct item_data *id; - id=numdb_search(item_db,nameid); + id=(struct item_data *) numdb_search(item_db,nameid); if(id) return id; id=(struct item_data *)aCalloc(1,sizeof(struct item_data)); @@ -152,7 +159,7 @@ struct item_data* itemdb_search(int nameid) id->weight=10; id->sex=2; id->elv=0; - id->class=0xffffffff; + id->class_=0xffffffff; id->flag.available=0; id->flag.value_notdc=0; //ˆê‰žEEE id->flag.value_notoc=0; @@ -237,66 +244,40 @@ int itemdb_isdropable(int nameid) return 1; } -// -// ‰Šú‰» -// -/*========================================== - * - *------------------------------------------ - */ -static int itemdb_read_itemslottable(void) -{ - char *buf,*p; - int s; - - buf=grfio_read("data\\itemslottable.txt"); - if(buf==NULL) - return -1; - s=grfio_size("data\\itemslottable.txt"); - buf[s]=0; - for(p=buf;p-buf<s;){ - int nameid,equip; - sscanf(p,"%d#%d#",&nameid,&equip); - itemdb_search(nameid)->equip=equip; - p=strchr(p,10); - if(!p) break; - p++; - p=strchr(p,10); - if(!p) break; - p++; - } - free(buf); - - return 0; -} - -#ifndef TXT_ONLY /*==================================== * Removed item_value_db, don't re-add *------------------------------------ */ static void itemdb_read(void) { - itemdb_read_itemslottable(); - - if (db_use_sqldbs) - { - itemdb_read_sqldb(); - } - else - { + #ifndef TXT_ONLY + if (db_use_sqldbs) + { + itemdb_read_sqldb(); + } + else + { + itemdb_readdb(); + } + /* not TXT_ONLY */ + #else itemdb_readdb(); - } + #endif /* TXT_ONLY */ itemdb_read_randomitem(); itemdb_read_itemavail(); itemdb_read_noequip(); - - if (!battle_config.item_name_override_grffile) + itemdb_read_norefine(); + if (battle_config.cardillust_read_grffile) + itemdb_read_cardillustnametable(); + if (battle_config.item_equip_override_grffile) + itemdb_read_itemslottable(); + if (battle_config.item_slots_override_grffile) + itemdb_read_itemslotcounttable(); + if (battle_config.item_name_override_grffile) itemdb_read_itemnametable(); } -#endif /* not TXT_ONLY */ /*========================================== * ƒAƒCƒeƒ€ƒf[ƒ^ƒx[ƒX‚̓ǂݞ‚Ý *------------------------------------------ @@ -346,20 +327,36 @@ static int itemdb_readdb(void) memcpy(id->name,str[1],24); memcpy(id->jname,str[2],24); id->type=atoi(str[3]); - // buy‚sell*2 ‚Í item_value_db.txt ‚ÅŽw’肵‚Ä‚‚¾‚³‚¢B - if (atoi(str[5])) { // sell’l‚ð—Dæ‚Æ‚·‚é - id->value_buy=atoi(str[5])*2; - id->value_sell=atoi(str[5]); - } else { - id->value_buy=atoi(str[4]); - id->value_sell=atoi(str[4])/2; + + { + int buy = atoi(str[4]), sell = atoi(str[5]); + // if buying price > selling price * 2 consider it valid and don't change it [celest] + if (buy && sell && buy > sell*2){ + id->value_buy = buy; + id->value_sell = sell; + } else { + // buy‚sell*2 ‚Í item_value_db.txt ‚ÅŽw’肵‚Ä‚‚¾‚³‚¢B + if (sell) { // sell’l‚ð—Dæ‚Æ‚·‚é + id->value_buy = sell*2; + id->value_sell = sell; + } else { + id->value_buy = buy; + id->value_sell = buy/2; + } + } + // check for bad prices that can possibly cause exploits + if (id->value_buy*75/100 < id->value_sell*124/100) { + sprintf (tmp_output, "Item %s [%d] buying:%d < selling:%d\n", + id->name, id->nameid, id->value_buy*75/100, id->value_sell*124/100); + ShowWarning (tmp_output); + } } id->weight=atoi(str[6]); id->atk=atoi(str[7]); id->def=atoi(str[8]); id->range=atoi(str[9]); id->slot=atoi(str[10]); - id->class=atoi(str[11]); + id->class_=atoi(str[11]); id->sex=atoi(str[12]); if(id->equip != atoi(str[13])){ id->equip=atoi(str[13]); @@ -377,13 +374,17 @@ static int itemdb_readdb(void) if((p=strchr(np,'{'))==NULL) continue; - id->use_script = parse_script(p,lines); + id->use_script = parse_script((unsigned char *) p,lines); if((p=strchr(p+1,'{'))==NULL) continue; - id->equip_script = parse_script(p,lines); + id->equip_script = parse_script((unsigned char *) p,lines); } fclose(fp); - printf("read %s done (count=%d)\n",filename[i],ln); + if (ln > 0) { + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,filename[i]); + ShowStatus(tmp_output); + } + ln=0; // reset to 0 } return 0; } @@ -410,15 +411,16 @@ static int itemdb_read_randomitem() {"db/item_bluebox.txt", blue_box, &blue_box_count, &blue_box_default }, {"db/item_violetbox.txt", violet_box, &violet_box_count, &violet_box_default }, {"db/item_cardalbum.txt", card_album, &card_album_count, &card_album_default }, - {"db/item_giftbox.txt", gift_box, &gift_box_count, &gift_box_default }, - {"db/item_scroll.txt", scroll, &scroll_count, &scroll_default }, + {"db/item_giftbox.txt", gift_box, &gift_box_count, &gift_box_default }, + {"db/item_scroll.txt", scroll, &scroll_count, &scroll_default }, + {"db/item_findingore.txt", finding_ore,&finding_ore_count, &finding_ore_default }, }; for(i=0;i<sizeof(data)/sizeof(data[0]);i++){ struct random_item_data *pd=data[i].pdata; int *pc=data[i].pcount; int *pdefault=data[i].pdefault; - char *fn=data[i].filename; + char *fn=(char *) data[i].filename; *pdefault = 0; if( (fp=fopen(fn,"r"))==NULL ){ @@ -458,7 +460,10 @@ static int itemdb_read_randomitem() ln++; } fclose(fp); - printf("read %s done (count=%d)\n",fn,*pc); + if (*pc > 0) { + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",*pc,fn); + ShowStatus(tmp_output); + } } return 0; @@ -507,7 +512,8 @@ static int itemdb_read_itemavail(void) ln++; } fclose(fp); - printf("read db/item_avail.txt done (count=%d)\n",ln); + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/item_avail.txt"); + ShowStatus(tmp_output); return 0; } @@ -520,7 +526,7 @@ static int itemdb_read_itemnametable(void) char *buf,*p; int s; - buf=grfio_reads("data\\idnum2itemdisplaynametable.txt",&s); + buf=(char *) grfio_reads("data\\idnum2itemdisplaynametable.txt",&s); if(buf==NULL) return -1; @@ -547,12 +553,13 @@ static int itemdb_read_itemnametable(void) if(!p) break; p++; } - free(buf); - printf("read data\\idnum2itemdisplaynametable.txt done.\n"); + aFree(buf); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\idnum2itemdisplaynametable.txt"); + ShowStatus(tmp_output); return 0; } -#ifdef TXT_ONLY + /*========================================== * ƒJ[ƒhƒCƒ‰ƒXƒg‚ÌƒŠƒ\[ƒX–¼‘Oƒe[ƒuƒ‹‚ð“ǂݞ‚Þ *------------------------------------------ @@ -562,7 +569,7 @@ static int itemdb_read_cardillustnametable(void) char *buf,*p; int s; - buf=grfio_reads("data\\num2cardillustnametable.txt",&s); + buf=(char *) grfio_reads("data\\num2cardillustnametable.txt",&s); if(buf==NULL) return -1; @@ -582,12 +589,83 @@ static int itemdb_read_cardillustnametable(void) if(!p) break; p++; } - free(buf); - printf("read data\\num2cardillustnametable.txt done.\n"); + aFree(buf); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\num2cardillustnametable.txt"); + ShowStatus(tmp_output); + + return 0; +} + +// +// ‰Šú‰» +// +/*========================================== + * + *------------------------------------------ + */ +static int itemdb_read_itemslottable(void) +{ + char *buf,*p; + int s; + + buf=(char *) grfio_read("data\\itemslottable.txt"); + if(buf==NULL) + return -1; + s=grfio_size("data\\itemslottable.txt"); + buf[s]=0; + for(p=buf;p-buf<s;){ + int nameid,equip; + struct item_data* item; + sscanf(p,"%d#%d#",&nameid,&equip); + item = itemdb_search(nameid); + if (item && itemdb_isequip2(item)) + item->equip=equip; + p=strchr(p,10); + if(!p) break; + p++; + p=strchr(p,10); + if(!p) break; + p++; + } + aFree(buf); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\itemslottable.txt"); + ShowStatus(tmp_output); + + return 0; +} + +/*========================================== + * + *------------------------------------------ + */ +static int itemdb_read_itemslotcounttable(void) +{ + char *buf,*p; + int s; + + buf=(char *) grfio_read("data\\itemslotcounttable.txt"); + if(buf==NULL) + return -1; + s=grfio_size("data\\itemslotcounttable.txt"); + buf[s]=0; + for(p=buf;p-buf<s;){ + int nameid,slot; + sscanf(p,"%d#%d#",&nameid,&slot); + itemdb_search(nameid)->slot=slot; + p=strchr(p,10); + if(!p) break; + p++; + p=strchr(p,10); + if(!p) break; + p++; + } + aFree(buf); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\itemslotcounttable.txt"); + ShowStatus(tmp_output); return 0; } -#endif /* TXT_ONLY */ + /*========================================== * ‘•”õ§ŒÀƒtƒ@ƒCƒ‹“Ç‚Ýo‚µ *------------------------------------------ @@ -627,9 +705,47 @@ static int itemdb_read_noequip(void) } fclose(fp); - printf("read db/item_noequip.txt done (count=%d)\n",ln); + if (ln > 0) { + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/item_noequip.txt"); + ShowStatus(tmp_output); + } return 0; } + +/*================================================ + * Whether the item can be refined or not [Celest] + *------------------------------------------------ + */ +static int itemdb_read_norefine(void) +{ + int i, nameid; + struct item_data *id; + // To-do: let it read from a text file later + int cant_refine[] = { + 1243, 1530, 2110, 2112, 2201, 2202, 2203, 2204, 2205, 2210, + 2212, 2218, 2219, 2237, 2238, 2239, 2240, 2241, 2242, 2243, + 2250, 2253, 2260, 2262, 2263, 2264, 2265, 2266, 2267, 2268, + 2269, 2270, 2271, 2276, 2278, 2279, 2281, 2282, 2286, 2288, + 2289, 2290, 2291, 2292, 2293, 2295, 2296, 2297, 2298, 2352, + 2410, 2413, 2414, 2509, 2510, 2601, 2602, 2603, 2604, 2605, + 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, + 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, + 2627, 2628, 2629, 2630, 2631, 2634, 2635, 2636, 2637, 2638, + 2639, 2640, 5004, 5005, 5006, 5008, 5014, 5015, 5037, 5039, + 5040, 5043, 5046, 5049, 5050, 5051, 5053, 5054, 5055, 5058, + 5068, 5074, 5085, 5086, 5087, 5088, 5089, 5090, 5096, 5098, 0 + }; + + for (i=0; i < (int)(sizeof(cant_refine) / sizeof(cant_refine[0])); i++) { + nameid = cant_refine[i]; + if(nameid<=0 || nameid>=20000 || !(id=itemdb_exists(nameid))) + continue; + id->flag.no_refine = 1; + } + + return 1; +} + #ifndef TXT_ONLY /*====================================== @@ -673,7 +789,7 @@ static int itemdb_read_sqldb(void) // Insert a new row into the item database - /*id = calloc(sizeof(struct item_data), 1); + /*id = aCalloc(sizeof(struct item_data), 1); if (id == NULL) { @@ -723,7 +839,7 @@ static int itemdb_read_sqldb(void) id->def = (sql_row[8] != NULL) ? atoi(sql_row[8]) : 0; id->range = (sql_row[9] != NULL) ? atoi(sql_row[9]) : 0; id->slot = (sql_row[10] != NULL) ? atoi(sql_row[10]) : 0; - id->class = (sql_row[11] != NULL) ? atoi(sql_row[11]) : 0; + id->class_ = (sql_row[11] != NULL) ? atoi(sql_row[11]) : 0; id->sex = (sql_row[12] != NULL) ? atoi(sql_row[12]) : 0; id->equip = (sql_row[13] != NULL) ? atoi(sql_row[13]) : 0; id->wlv = (sql_row[14] != NULL) ? atoi(sql_row[14]) : 0; @@ -737,10 +853,10 @@ static int itemdb_read_sqldb(void) if (sql_row[17] != NULL) { if (sql_row[17][0] == '{') - id->use_script = parse_script(sql_row[17], 0); + id->use_script = parse_script((unsigned char *) sql_row[17], 0); else { sprintf(script, "{%s}", sql_row[17]); - id->use_script = parse_script(script, 0); + id->use_script = parse_script((unsigned char *) script, 0); } } else @@ -751,10 +867,10 @@ static int itemdb_read_sqldb(void) if (sql_row[18] != NULL) { if (sql_row[18][0] == '{') - id->equip_script = parse_script(sql_row[18], 0); + id->equip_script = parse_script((unsigned char *) sql_row[18], 0); else { sprintf(script, "{%s}", sql_row[18]); - id->equip_script = parse_script(script, 0); + id->equip_script = parse_script((unsigned char *) script, 0); } } else @@ -774,8 +890,8 @@ static int itemdb_read_sqldb(void) { printf("Database server error (retrieving rows from %s): %s\n", item_db_db, mysql_error(&mmysql_handle)); } - - printf("read %s done (count = %lu)\n", item_db_db, (unsigned long) mysql_num_rows(sql_res)); + sprintf(tmp_output,"Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",(unsigned long) mysql_num_rows(sql_res),item_db_db); + ShowStatus(tmp_output); } else { @@ -802,26 +918,20 @@ static int itemdb_final(void *key,void *data,va_list ap) { struct item_data *id; - nullpo_retr(0, id=data); + nullpo_retr(0, id= (struct item_data *) data); if(id->use_script) - free(id->use_script); + aFree(id->use_script); if(id->equip_script) - free(id->equip_script); - free(id); + aFree(id->equip_script); + aFree(id); return 0; } void itemdb_reload(void) { - /* - - <empty item databases> - itemdb_read(); - - */ - + numdb_final(item_db,itemdb_final); do_init_itemdb(); } @@ -851,23 +961,6 @@ void itemdebugtxt() fclose(dfp); } */ -#ifdef TXT_ONLY -/*==================================== - * Removed item_value_db, don't re-add - *------------------------------------ - */ -static void itemdb_read(void) -{ - itemdb_read_itemslottable(); - itemdb_readdb(); - itemdb_read_randomitem(); - itemdb_read_itemavail(); - itemdb_read_noequip(); - itemdb_read_cardillustnametable(); - if (!battle_config.item_name_override_grffile) - itemdb_read_itemnametable(); -} -#endif /* TXT_ONLY */ /*========================================== * *------------------------------------------ diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 0edfad243..2ba6ae7f6 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -12,7 +12,7 @@ struct item_data { int value_buy; int value_sell; int type; - int class; + int class_; int sex; int equip; int weight; @@ -33,6 +33,7 @@ struct item_data { unsigned no_equip : 3; unsigned no_drop : 1; unsigned no_use : 1; + unsigned no_refine : 1; // [celest] } flag; int view_id; }; diff --git a/src/map/log.c b/src/map/log.c index 86c5a41a2..7cf4dfcf4 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -3,69 +3,117 @@ #include <stdio.h> #include <string.h> +#include "../common/strlib.h" +#include "../common/nullpo.h" +#include "itemdb.h" #include "map.h" -#include "nullpo.h" #include "log.h" struct Log_Config log_config; +char timestring[255]; +time_t curtime; + +//FILTER OPTIONS +//0 = Don't log +//1 = Log any item +//Bits: || +//2 - Healing items (0) +//3 - Etc Items(3) + Arrows (10) +//4 - Usable Items(2) +//5 - Weapon(4) +//6 - Shields,Armor,Headgears,Accessories,etc(5) +//7 - Cards(6) +//8 - Pet Accessories(8) + Eggs(7) (well, monsters don't drop 'em but we'll use the same system for ALL logs) +//9 - Log expensive items ( >= price_log) +//10 - Log big amount of items ( >= amount_log) +//11 - Log refined items (if their refine >= refine_log ) +//12 - Log rare items (if their drop chance <= rare_log ) + +//check if this item should be logger according the settings +int should_log_item(int filter, int nameid) { + struct item_data *item_data; + if (nameid<512 || (item_data= itemdb_search(nameid)) == NULL) return 0; + if ( (filter&1) || // Filter = 1, we log any item + (filter&2 && item_data->type == 0 ) || //healing items + (filter&4 && (item_data->type == 3 || item_data->type == 10) ) || //etc+arrows + (filter&8 && item_data->type == 2 ) || //usable + (filter&16 && item_data->type == 4 ) || //weapon + (filter&32 && item_data->type == 5 ) || //armor + (filter&64 && item_data->type == 6 ) || //cards + (filter&128 && (item_data->type == 7 || item_data->type == 8) ) || //eggs+pet access + (filter&256 && item_data->value_buy >= log_config.price_items_log ) || + (filter&512 && item_data->refine >= log_config.refine_items_log ) + ) return item_data->nameid; + + return 0; +} + int log_branch(struct map_session_data *sd) { +#ifndef TXT_ONLY + char t_name[100]; +#endif FILE *logfp; if(log_config.enable_logs <= 0) return 0; nullpo_retr(0, sd); - #ifndef TXT_ONLY +#ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%s')", log_config.log_branch_db, sd->status.account_id, sd->status.char_id, sd->status.name, sd->mapname); + sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%s')", + log_config.log_branch_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), sd->mapname); if(mysql_query(&mmysql_handle, tmp_sql)) printf("DB server Error - %s\n",mysql_error(&mmysql_handle)); } else { - #endif - if((logfp=fopen(log_config.log_drop,"a+")) != NULL) { - char timestring[255]; - time_t curtime; +#endif + if((logfp=fopen(log_config.log_branch,"a+")) != NULL) { time(&curtime); strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp,"%s - %s[%d:%d]\t%s%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, sd->mapname, RETCODE); fclose(logfp); } - #ifndef TXT_ONLY +#ifndef TXT_ONLY } - #endif +#endif return 0; } int log_drop(struct map_session_data *sd, int monster_id, int *log_drop) { FILE *logfp; + int i,flag = 0; if(log_config.enable_logs <= 0) return 0; nullpo_retr(0, sd); - #ifndef TXT_ONLY + for (i = 0; i<10; i++) { //Should we log these items? [Lupus] + flag += should_log_item(log_config.drop,log_drop[i]); + } + if (flag==0) return 0; //we skip logging this items set - they doesn't met our logging conditions [Lupus] + +#ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT INTO `%s` (`drop_date`, `kill_char_id`, `monster_id`, `item1`, `item2`, `item3`, `item4`, `item5`, `item6`, `item7`, `item8`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s') ", log_config.log_drop_db, sd->status.char_id, monster_id, log_drop[0], log_drop[1], log_drop[2], log_drop[3], log_drop[4], log_drop[5], log_drop[6], log_drop[7], sd->mapname); + sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`drop_date`, `kill_char_id`, `monster_id`, `item1`, `item2`, `item3`, `item4`, `item5`, `item6`, `item7`, `item8`, `item9`, `itemCard`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s') ", log_config.log_drop_db, sd->status.char_id, monster_id, log_drop[0], log_drop[1], log_drop[2], log_drop[3], log_drop[4], log_drop[5], log_drop[6], log_drop[7], log_drop[8], log_drop[9], sd->mapname); if(mysql_query(&mmysql_handle, tmp_sql)) printf("DB server Error - %s\n",mysql_error(&mmysql_handle)); } else { - #endif +#endif if((logfp=fopen(log_config.log_drop,"a+")) != NULL) { - char timestring[255]; + time_t curtime; time(&curtime); strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d,%d,%d,%d,%d,%d,%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_drop[0], log_drop[1], log_drop[2], log_drop[3], log_drop[4], log_drop[5], log_drop[6], log_drop[7], RETCODE); + fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_drop[0], log_drop[1], log_drop[2], log_drop[3], log_drop[4], log_drop[5], log_drop[6], log_drop[7], log_drop[8], log_drop[9], RETCODE); fclose(logfp); } - #ifndef TXT_ONLY +#ifndef TXT_ONLY } - #endif - return 0; +#endif + return 1; //Logged } int log_mvpdrop(struct map_session_data *sd, int monster_id, int *log_mvp) @@ -75,81 +123,87 @@ int log_mvpdrop(struct map_session_data *sd, int monster_id, int *log_mvp) if(log_config.enable_logs <= 0) return 0; nullpo_retr(0, sd); - #ifndef TXT_ONLY +#ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", log_config.log_mvpdrop_db, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], sd->mapname); + sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", log_config.log_mvpdrop_db, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], sd->mapname); if(mysql_query(&mmysql_handle, tmp_sql)) printf("DB server Error - %s\n",mysql_error(&mmysql_handle)); } else { - #endif +#endif if((logfp=fopen(log_config.log_mvpdrop,"a+")) != NULL) { - char timestring[255]; - time_t curtime; time(&curtime); strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], RETCODE); fclose(logfp); } - #ifndef TXT_ONLY +#ifndef TXT_ONLY } - #endif +#endif return 0; } int log_present(struct map_session_data *sd, int source_type, int nameid) { FILE *logfp; +#ifndef TXT_ONLY + char t_name[100]; +#endif + if(log_config.enable_logs <= 0) return 0; nullpo_retr(0, sd); - #ifndef TXT_ONLY + if(!should_log_item(log_config.present,nameid)) return 0; //filter [Lupus] +#ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT INTO `%s` (`present_date`, `src_id`, `account_id`, `char_id`, `char_name`, `nameid`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%s', '%d', '%s') ", log_config.log_present_db, source_type, sd->status.account_id, sd->status.char_id, sd->status.name, nameid, sd->mapname); + sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`present_date`, `src_id`, `account_id`, `char_id`, `char_name`, `nameid`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%s', '%d', '%s') ", + log_config.log_present_db, source_type, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), nameid, sd->mapname); if(mysql_query(&mmysql_handle, tmp_sql)) printf("DB server Error - %s\n",mysql_error(&mmysql_handle)); } else { - #endif +#endif if((logfp=fopen(log_config.log_present,"a+")) != NULL) { - char timestring[255]; - time_t curtime; time(&curtime); strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, source_type, nameid, RETCODE); fclose(logfp); } - #ifndef TXT_ONLY +#ifndef TXT_ONLY } - #endif +#endif return 0; } int log_produce(struct map_session_data *sd, int nameid, int slot1, int slot2, int slot3, int success) { FILE *logfp; +#ifndef TXT_ONLY + char t_name[100]; +#endif + if(log_config.enable_logs <= 0) return 0; nullpo_retr(0, sd); - #ifndef TXT_ONLY + if(!should_log_item(log_config.produce,nameid)) return 0; //filter [Lupus] +#ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT INTO `%s` (`produce_date`, `account_id`, `char_id`, `char_name`, `nameid`, `slot1`, `slot2`, `slot3`, `map`, `success`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%s', '%d') ", log_config.log_produce_db, sd->status.account_id, sd->status.char_id, sd->status.name, nameid, slot1, slot2, slot3, sd->mapname, success); + sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`produce_date`, `account_id`, `char_id`, `char_name`, `nameid`, `slot1`, `slot2`, `slot3`, `map`, `success`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%s', '%d') ", + log_config.log_produce_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), nameid, slot1, slot2, slot3, sd->mapname, success); if(mysql_query(&mmysql_handle, tmp_sql)) printf("DB server Error - %s\n",mysql_error(&mmysql_handle)); } else { - #endif +#endif if((logfp=fopen(log_config.log_produce,"a+")) != NULL) { - char timestring[255]; - time_t curtime; time(&curtime); strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d,%d\t%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, nameid, slot1, slot2, slot3, success, RETCODE); fclose(logfp); } - #ifndef TXT_ONLY +#ifndef TXT_ONLY } - #endif +#endif return 0; } @@ -159,6 +213,9 @@ int log_refine(struct map_session_data *sd, int n, int success) int log_card[4]; int item_level; int i; +#ifndef TXT_ONLY + char t_name[100]; +#endif if(log_config.enable_logs <= 0) return 0; @@ -169,37 +226,100 @@ int log_refine(struct map_session_data *sd, int n, int success) item_level = 0; else item_level = sd->status.inventory[n].refine + 1; - + if(!should_log_item(log_config.refine,sd->status.inventory[n].nameid)) return 0; //filter [Lupus] for(i=0;i<4;i++) log_card[i] = sd->status.inventory[n].card[i]; - #ifndef TXT_ONLY +#ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT INTO `%s` (`refine_date`, `account_id`, `char_id`, `char_name`, `nameid`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `success`, `item_level`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%d', '%d')", log_config.log_refine_db, sd->status.account_id, sd->status.char_id, sd->status.name, sd->status.inventory[n].nameid, sd->status.inventory[n].refine, log_card[0], log_card[1], log_card[2], log_card[3], sd->mapname, success, item_level); + sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`refine_date`, `account_id`, `char_id`, `char_name`, `nameid`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `success`, `item_level`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%d', '%d')", + log_config.log_refine_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), sd->status.inventory[n].nameid, sd->status.inventory[n].refine, log_card[0], log_card[1], log_card[2], log_card[3], sd->mapname, success, item_level); if(mysql_query(&mmysql_handle, tmp_sql)) printf("DB server Error - %s\n",mysql_error(&mmysql_handle)); } else { - #endif +#endif if((logfp=fopen(log_config.log_refine,"a+")) != NULL) { - char timestring[255]; - time_t curtime; time(&curtime); strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp,"%s - %s[%d:%d]\t%d,%d\t%d%d%d%d\t%d,%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, sd->status.inventory[n].nameid, sd->status.inventory[n].refine, log_card[0], log_card[1], log_card[2], log_card[3], success, item_level, RETCODE); fclose(logfp); } - #ifndef TXT_ONLY +#ifndef TXT_ONLY } - #endif +#endif return 0; } +int log_tostorage(struct map_session_data *sd,int n, int guild) +{ + FILE *logfp; + + if(log_config.enable_logs <= 0 || log_config.storage == 0 || log_config.log_storage[0] == '\0') + return 0; + + nullpo_retr(0, sd); + if(sd->status.inventory[n].nameid==0 || sd->inventory_data[n] == NULL) + return 1; + + if(sd->status.inventory[n].amount < 0) + return 1; + + if((logfp=fopen(log_config.log_trade,"a+")) != NULL) { + time(&curtime); + strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp,"%s - to %s: %s[%d:%d]\t%d\t%d\t%d\t%d,%d,%d,%d%s", timestring, guild ? "guild_storage": "storage", sd->status.name, sd->status.account_id, sd->status.char_id, + sd->status.inventory[n].nameid, + sd->status.inventory[n].amount, + sd->status.inventory[n].refine, + sd->status.inventory[n].card[0], + sd->status.inventory[n].card[1], + sd->status.inventory[n].card[2], + sd->status.inventory[n].card[3], RETCODE); + fclose(logfp); + } + return 0; +} + +int log_fromstorage(struct map_session_data *sd,int n, int guild) +{ + FILE *logfp; + + if(log_config.enable_logs <= 0 || log_config.storage == 0 || log_config.log_storage[0] == '\0') + return 0; + + nullpo_retr(0, sd); + + if(sd->status.inventory[n].nameid==0 || sd->inventory_data[n] == NULL) + return 1; + + if(sd->status.inventory[n].amount < 0) + return 1; + + if((logfp=fopen(log_config.log_trade,"a+")) != NULL) { + time(&curtime); + strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp,"%s - from %s: %s[%d:%d]\t%d\t%d\t%d\t%d,%d,%d,%d%s", timestring, guild ? "guild_storage": "storage", sd->status.name, sd->status.account_id, sd->status.char_id, + sd->status.inventory[n].nameid, + sd->status.inventory[n].amount, + sd->status.inventory[n].refine, + sd->status.inventory[n].card[0], + sd->status.inventory[n].card[1], + sd->status.inventory[n].card[2], + sd->status.inventory[n].card[3], RETCODE); + fclose(logfp); + } + return 0; +} + int log_trade(struct map_session_data *sd, struct map_session_data *target_sd, int n,int amount) { FILE *logfp; int log_nameid, log_amount, log_refine, log_card[4]; int i; +#ifndef TXT_ONLY + char t_name[100],t_name2[100]; +#endif if(log_config.enable_logs <= 0) return 0; @@ -211,7 +331,7 @@ int log_trade(struct map_session_data *sd, struct map_session_data *target_sd, i if(sd->status.inventory[n].amount < 0) return 1; - + if(!should_log_item(log_config.trade,sd->status.inventory[n].nameid)) return 0; //filter [Lupus] log_nameid = sd->status.inventory[n].nameid; log_amount = sd->status.inventory[n].amount; log_refine = sd->status.inventory[n].refine; @@ -219,25 +339,24 @@ int log_trade(struct map_session_data *sd, struct map_session_data *target_sd, i for(i=0;i<4;i++) log_card[i] = sd->status.inventory[n].card[i]; - #ifndef TXT_ONLY +#ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT INTO `%s` (`trade_date`, `src_account_id`, `src_char_id`, `src_char_name`, `des_account_id`, `des_char_id`, `des_char_name`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", log_config.log_trade_db, sd->status.account_id, sd->status.char_id, sd->status.name, target_sd->status.account_id, target_sd->status.char_id, target_sd->status.name, log_nameid, log_amount, log_refine, log_card[0], log_card[1], log_card[2], log_card[3], sd->mapname); + sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`trade_date`, `src_account_id`, `src_char_id`, `src_char_name`, `des_account_id`, `des_char_id`, `des_char_name`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", + log_config.log_trade_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), target_sd->status.account_id, target_sd->status.char_id, jstrescapecpy(t_name2, target_sd->status.name), log_nameid, log_amount, log_refine, log_card[0], log_card[1], log_card[2], log_card[3], sd->mapname); if(mysql_query(&mmysql_handle, tmp_sql)) printf("DB server Error - %s\n",mysql_error(&mmysql_handle)); } else { - #endif +#endif if((logfp=fopen(log_config.log_trade,"a+")) != NULL) { - char timestring[255]; - time_t curtime; time(&curtime); strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp,"%s - %s[%d:%d]\t%s[%d:%d]\t%d\t%d\t%d\t%d,%d,%d,%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, target_sd->status.name, target_sd->status.account_id, target_sd->status.char_id, log_nameid, log_amount, log_refine, log_card[0], log_card[1], log_card[2], log_card[3], RETCODE); fclose(logfp); } - #ifndef TXT_ONLY +#ifndef TXT_ONLY } - #endif +#endif return 0; } @@ -246,6 +365,9 @@ int log_vend(struct map_session_data *sd,struct map_session_data *vsd,int n,int FILE *logfp; int log_nameid, log_amount, log_refine, log_card[4]; int i; +#ifndef TXT_ONLY + char t_name[100],t_name2[100]; +#endif if(log_config.enable_logs <= 0) return 0; @@ -255,88 +377,124 @@ int log_vend(struct map_session_data *sd,struct map_session_data *vsd,int n,int return 1; if(sd->status.inventory[n].amount< 0) return 1; - + if(!should_log_item(log_config.vend,sd->status.inventory[n].nameid)) return 0; //filter [Lupus] log_nameid = sd->status.inventory[n].nameid; log_amount = sd->status.inventory[n].amount; log_refine = sd->status.inventory[n].refine; for(i=0;i<4;i++) log_card[i] = sd->status.inventory[n].card[i]; - #ifndef TXT_ONLY +#ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT INTO `%s` (`vend_date`, `vend_account_id`, `vend_char_id`, `vend_char_name`, `buy_account_id`, `buy_char_id`, `buy_char_name`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `zeny`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%d')", log_config.log_vend_db, sd->status.account_id, sd->status.char_id, sd->status.name, vsd->status.account_id, vsd->status.char_id, vsd->status.name, log_nameid, log_amount, log_refine, log_card[0], log_card[1], log_card[2], log_card[3], sd->mapname, zeny); + sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`vend_date`, `vend_account_id`, `vend_char_id`, `vend_char_name`, `buy_account_id`, `buy_char_id`, `buy_char_name`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `zeny`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%d')", + log_config.log_vend_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), vsd->status.account_id, vsd->status.char_id, jstrescapecpy(t_name2, vsd->status.name), log_nameid, log_amount, log_refine, log_card[0], log_card[1], log_card[2], log_card[3], sd->mapname, zeny); if(mysql_query(&mmysql_handle, tmp_sql)) printf("DB server Error - %s\n",mysql_error(&mmysql_handle)); } else { - #endif +#endif if((logfp=fopen(log_config.log_vend,"a+")) != NULL) { - char timestring[255]; - time_t curtime; time(&curtime); strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp,"%s - %s[%d:%d]\t%s[%d:%d]\t%d\t%d\t%d\t%d,%d,%d,%d\t%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, vsd->status.name, vsd->status.account_id, vsd->status.char_id, log_nameid, log_amount, log_refine, log_card[0], log_card[1], log_card[2], log_card[3], zeny, RETCODE); fclose(logfp); } - #ifndef TXT_ONLY +#ifndef TXT_ONLY } - #endif +#endif return 0; } int log_zeny(struct map_session_data *sd, struct map_session_data *target_sd,int amount) { FILE *logfp; +#ifndef TXT_ONLY + char t_name[100],t_name2[100]; +#endif + if(log_config.enable_logs <= 0) return 0; nullpo_retr(0, sd); - #ifndef TXT_ONLY +#ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql,"INSERT INTO `%s` (`trade_date`, `src_account_id`, `src_char_id`, `src_char_name`, `des_account_id`, `des_char_id`, `des_char_name`, `map`, `zeny`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%s', '%s', '%d')", log_config.log_trade_db, sd->status.account_id, sd->status.char_id, sd->status.name, target_sd->status.account_id, target_sd->status.char_id, target_sd->status.name, sd->mapname, sd->deal_zeny); + sprintf(tmp_sql,"INSERT DELAYED INTO `%s` (`trade_date`, `src_account_id`, `src_char_id`, `src_char_name`, `des_account_id`, `des_char_id`, `des_char_name`, `map`, `zeny`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%s', '%s', '%d')", + log_config.log_trade_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), target_sd->status.account_id, target_sd->status.char_id, jstrescapecpy(t_name2, target_sd->status.name), sd->mapname, sd->deal_zeny); if(mysql_query(&mmysql_handle, tmp_sql)) printf("DB server Error - %s\n",mysql_error(&mmysql_handle)); } else { - #endif +#endif if((logfp=fopen(log_config.log_trade,"a+")) != NULL) { - char timestring[255]; - time_t curtime; time(&curtime); strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp,"%s - %s[%d]\t%s[%d]\t%d\t%s", timestring, sd->status.name, sd->status.account_id, target_sd->status.name, target_sd->status.account_id, sd->deal_zeny, RETCODE); fclose(logfp); } - #ifndef TXT_ONLY +#ifndef TXT_ONLY } - #endif +#endif return 0; } int log_atcommand(struct map_session_data *sd, const char *message) { FILE *logfp; +#ifndef TXT_ONLY + char t_name[100]; +#endif + if(log_config.enable_logs <= 0) return 0; nullpo_retr(0, sd); - #ifndef TXT_ONLY +#ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES(NOW(), '%d', '%d', '%s', '%s', '%s') ", log_config.log_gm_db, sd->status.account_id, sd->status.char_id, sd->status.name, sd->mapname, message); + sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES(NOW(), '%d', '%d', '%s', '%s', '%s') ", + log_config.log_gm_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), sd->mapname, message); if(mysql_query(&mmysql_handle, tmp_sql)) printf("DB server Error - %s\n",mysql_error(&mmysql_handle)); } else { - #endif +#endif if((logfp=fopen(log_config.log_gm,"a+")) != NULL) { - char timestring[255]; - time_t curtime; time(&curtime); strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp,"%s - %s[%d]: %s%s",timestring,sd->status.name,sd->status.account_id,message,RETCODE); fclose(logfp); } - #ifndef TXT_ONLY +#ifndef TXT_ONLY } +#endif + return 0; +} + +int log_npc(struct map_session_data *sd, const char *message) +{ //[Lupus] + FILE *logfp; + #ifndef TXT_ONLY + char t_name[100]; #endif + + if(log_config.enable_logs <= 0) + return 0; + nullpo_retr(0, sd); +#ifndef TXT_ONLY + if(log_config.sql_logs > 0) + { + sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES(NOW(), '%d', '%d', '%s', '%s', '%s') ", + log_config.log_npc_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), sd->mapname, message); + if(mysql_query(&mmysql_handle, tmp_sql)) + printf("DB server Error - %s\n",mysql_error(&mmysql_handle)); + } else { +#endif + if((logfp=fopen(log_config.log_npc,"a+")) != NULL) { + time(&curtime); + strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp,"%s - %s[%d]: %s%s",timestring,sd->status.name,sd->status.account_id,message,RETCODE); + fclose(logfp); + } +#ifndef TXT_ONLY + } +#endif return 0; } @@ -345,11 +503,19 @@ int log_config_read(char *cfgName) char line[1024], w1[1024], w2[1024]; FILE *fp; + memset(&log_config, 0, sizeof(log_config)); + if((fp = fopen(cfgName, "r")) == NULL) { printf("Log configuration file not found at: %s\n", cfgName); return 1; } + + //LOG FILTER Default values + log_config.refine_items_log = 7; //log refined items, with refine >= +7 + log_config.rare_items_log = 100; //log rare items. drop chance <= 1% + log_config.price_items_log = 1000; //1000z + log_config.amount_items_log = 100; while(fgets(line, sizeof(line) -1, fp)) { @@ -362,6 +528,16 @@ int log_config_read(char *cfgName) log_config.enable_logs = (atoi(w2)); } else if(strcmpi(w1,"sql_logs") == 0) { log_config.sql_logs = (atoi(w2)); +//start of common filter settings + } else if(strcmpi(w1,"rare_items_log") == 0) { + log_config.rare_items_log = (atoi(w2)); + } else if(strcmpi(w1,"refine_items_log") == 0) { + log_config.refine_items_log = (atoi(w2)); + } else if(strcmpi(w1,"price_items_log") == 0) { + log_config.price_items_log = (atoi(w2)); + } else if(strcmpi(w1,"amount_items_log") == 0) { + log_config.amount_items_log = (atoi(w2)); +//end of common filter settings } else if(strcmpi(w1,"log_branch") == 0) { log_config.branch = (atoi(w2)); } else if(strcmpi(w1,"log_drop") == 0) { @@ -376,6 +552,8 @@ int log_config_read(char *cfgName) log_config.refine = (atoi(w2)); } else if(strcmpi(w1,"log_trade") == 0) { log_config.trade = (atoi(w2)); + } else if(strcmpi(w1,"log_storage") == 0) { + log_config.storage = (atoi(w2)); } else if(strcmpi(w1,"log_vend") == 0) { log_config.vend = (atoi(w2)); } else if(strcmpi(w1,"log_zeny") == 0) { @@ -383,10 +561,13 @@ int log_config_read(char *cfgName) log_config.zeny = 0; else log_config.zeny = (atoi(w2)); - } else if(strcmpi(w1,"log_gm") == 0) { + } else if(strcmpi(w1,"log_gm") == 0) { log_config.gm = (atoi(w2)); + } else if(strcmpi(w1,"log_npc") == 0) { + log_config.npc = (atoi(w2)); } +#ifndef TXT_ONLY else if(strcmpi(w1, "log_branch_db") == 0) { strcpy(log_config.log_branch_db, w2); if(log_config.branch == 1) @@ -420,6 +601,13 @@ int log_config_read(char *cfgName) printf("and Zeny Trades"); printf(" to table `%s`\n", w2); } +// } else if(strcmpi(w1, "log_storage_db") == 0) { +// strcpy(log_config.log_storage_db, w2); +// if(log_config.storage == 1) +// { +// printf("Logging Item Storages"); +// printf(" to table `%s`\n", w2); +// } } else if(strcmpi(w1, "log_vend_db") == 0) { strcpy(log_config.log_vend_db, w2); if(log_config.vend == 1) @@ -428,49 +616,68 @@ int log_config_read(char *cfgName) strcpy(log_config.log_gm_db, w2); if(log_config.gm > 0) printf("Logging GM Level %d Commands to table `%s`\n", log_config.gm, w2); + } else if(strcmpi(w1, "log_npc_db") == 0) { + strcpy(log_config.log_npc_db, w2); + if(log_config.npc > 0) + printf("Logging NPC 'logmes' to table `%s`\n", w2); } +#endif - else if(strcmpi(w1, "log_branch") == 0) { + else if(strcmpi(w1, "log_branch_file") == 0) { strcpy(log_config.log_branch, w2); - if(log_config.branch == 1) + if(log_config.branch > 0 && log_config.sql_logs < 1) printf("Logging Dead Branch Usage to file `%s`.txt\n", w2); - } else if(strcmpi(w1, "log_drop") == 0) { + } else if(strcmpi(w1, "log_drop_file") == 0) { strcpy(log_config.log_drop, w2); - if(log_config.drop == 1) + if(log_config.drop > 0 && log_config.sql_logs < 1) printf("Logging Item Drops to file `%s`.txt\n", w2); - } else if(strcmpi(w1, "log_mvpdrop") == 0) { + } else if(strcmpi(w1, "log_mvpdrop_file") == 0) { strcpy(log_config.log_mvpdrop, w2); - if(log_config.mvpdrop == 1) + if(log_config.mvpdrop > 0 && log_config.sql_logs < 1) printf("Logging MVP Drops to file `%s`.txt\n", w2); - } else if(strcmpi(w1, "log_present") == 0) { + } else if(strcmpi(w1, "log_present_file") == 0) { strcpy(log_config.log_present, w2); - if(log_config.present == 1) + if(log_config.present > 0 && log_config.sql_logs < 1) printf("Logging Present Usage & Results to file `%s`.txt\n", w2); - } else if(strcmpi(w1, "log_produce") == 0) { + } else if(strcmpi(w1, "log_produce_file") == 0) { strcpy(log_config.log_produce, w2); - if(log_config.produce == 1) + if(log_config.produce > 0 && log_config.sql_logs < 1) printf("Logging Producing to file `%s`.txt\n", w2); - } else if(strcmpi(w1, "log_refine") == 0) { + } else if(strcmpi(w1, "log_refine_file") == 0) { strcpy(log_config.log_refine, w2); - if(log_config.refine == 1) + if(log_config.refine > 0 && log_config.sql_logs < 1) printf("Logging Refining to file `%s`.txt\n", w2); - } else if(strcmpi(w1, "log_trade") == 0) { + } else if(strcmpi(w1, "log_trade_file") == 0) { strcpy(log_config.log_trade, w2); - if(log_config.trade == 1) + if(log_config.trade > 0 && log_config.sql_logs < 1) { printf("Logging Item Trades"); - if(log_config.zeny == 1) + if(log_config.zeny > 0) printf("and Zeny Trades"); printf(" to file `%s`.txt\n", w2); } - } else if(strcmpi(w1, "log_vend") == 0) { + } else if(strcmpi(w1, "log_storage_file") == 0) { + strcpy(log_config.log_storage, w2); + if(log_config.storage > 0 && log_config.sql_logs < 1) + { + printf("Logging Item Storages"); + printf(" to file `%s`.txt\n", w2); + } + } else if(strcmpi(w1, "log_vend_file") == 0) { strcpy(log_config.log_vend, w2); - if(log_config.vend == 1) + if(log_config.vend > 0 && log_config.sql_logs < 1) printf("Logging Vending to file `%s`.txt\n", w2); - } else if(strcmpi(w1, "log_gm") == 0) { + } else if(strcmpi(w1, "log_gm_file") == 0) { strcpy(log_config.log_gm, w2); - if(log_config.gm > 0) + if(log_config.gm > 0 && log_config.sql_logs < 1) printf("Logging GM Level %d Commands to file `%s`.txt\n", log_config.gm, w2); + } else if(strcmpi(w1, "log_npc_file") == 0) { + strcpy(log_config.log_npc, w2); + if(log_config.npc > 0 && log_config.sql_logs < 1) + printf("Logging NPC 'logmes' to file `%s`.txt\n", w2); + //support the import command, just like any other config + } else if(strcmpi(w1,"import") == 0) { + log_config_read(w2); } } } diff --git a/src/map/log.h b/src/map/log.h index d4ad0bd66..cdb543f0d 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -16,18 +16,25 @@ int log_present(struct map_session_data *sd, int source_type, int nameid); int log_produce(struct map_session_data *sd, int nameid, int slot1, int slot2, int slot3, int success); int log_refine(struct map_session_data *sd, int n, int success); int log_trade(struct map_session_data *sd,struct map_session_data *target_sd,int n,int amount); +int log_tostorage(struct map_session_data *sd,int n, int guild); +int log_fromstorage(struct map_session_data *sd,int n, int guild); + int log_vend(struct map_session_data *sd,struct map_session_data *vsd,int n,int amount,int zeny); int log_zeny(struct map_session_data *sd, struct map_session_data *target_sd,int amount); int log_atcommand(struct map_session_data *sd, const char *message); +int log_npc(struct map_session_data *sd, const char *message); int log_config_read(char *cfgName); extern struct Log_Config { int enable_logs; int sql_logs; - int branch, drop, mvpdrop, present, produce, refine, trade, vend, zeny, gm; - char log_branch[32], log_drop[32], log_mvpdrop[32], log_present[32], log_produce[32], log_refine[32], log_trade[32], log_vend[32], log_gm[32]; - char log_branch_db[32], log_drop_db[32], log_mvpdrop_db[32], log_present_db[32], log_produce_db[32], log_refine_db[32], log_trade_db[32], log_vend_db[32], log_gm_db[32]; + int rare_items_log,refine_items_log,price_items_log,amount_items_log; + int branch, drop, mvpdrop, present, produce, refine, trade, vend, zeny, gm, npc, storage; + char log_branch[32], log_drop[32], log_mvpdrop[32], log_present[32], log_produce[32], log_refine[32], log_trade[32], log_vend[32], log_gm[32], log_npc[32], log_storage[32]; + char log_branch_db[32], log_drop_db[32], log_mvpdrop_db[32], log_present_db[32], log_produce_db[32], log_refine_db[32], log_trade_db[32], log_vend_db[32], log_gm_db[32], log_npc_db[32]; + int uptime; + char log_uptime[32]; } log_config; #endif diff --git a/src/map/mail.c b/src/map/mail.c index 019f6303d..42a83de52 100644 --- a/src/map/mail.c +++ b/src/map/mail.c @@ -1,18 +1,22 @@ +#ifndef TXT_ONLY // Mail System for eAthena SQL // Created by Valaris +// moved all strings to msg_athena.conf [Lupus] #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "socket.h" -#include "timer.h" -#include "nullpo.h" +#include "../common/strlib.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/nullpo.h" #include "map.h" #include "clif.h" #include "chrif.h" #include "intif.h" +#include "atcommand.h" #include "pc.h" #include "mail.h" @@ -20,6 +24,7 @@ char mail_db[32] = "mail"; int MAIL_CHECK_TIME = 120000; int mail_timer; +//extern char *msg_table[1000]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others) #ifdef MEMWATCH #include "memwatch.h" @@ -27,13 +32,13 @@ int mail_timer; int mail_check(struct map_session_data *sd,int type) { - int i=0,new=0,priority=0; + int i = 0, new_ = 0, priority = 0; char message[50]; - if(sd==NULL) - return 0; - - sprintf(tmp_msql,"SELECT `message_id`,`to_account_id`,`from_char_name`,`read_flag`,`priority`,`check_flag` FROM `%s` WHERE `to_account_id` = \"%d\" ORDER by `message_id`", mail_db, sd->status.account_id); + nullpo_retr (0, sd); + + sprintf(tmp_msql,"SELECT `message_id`,`to_account_id`,`from_char_name`,`read_flag`,`priority`,`check_flag` " + "FROM `%s` WHERE `to_account_id` = \"%d\" ORDER by `message_id`", mail_db, sd->status.account_id); if (mysql_query(&mail_handle, tmp_msql)) { printf("Database server error (executing query for %s): %s\n", mail_db, mysql_error(&mail_handle)); @@ -42,63 +47,66 @@ int mail_check(struct map_session_data *sd,int type) mail_res = mysql_store_result(&mail_handle); if(mail_res) { - if (mysql_num_rows(mail_res) == 0) { - clif_displaymessage(sd->fd,"You have no messages."); - mysql_free_result(mail_res); - return 0; - } + if (mysql_num_rows(mail_res) == 0) { + //clif_displaymessage(sd->fd,"You have no messages."); + clif_displaymessage(sd->fd, msg_txt(516)); - while ((mail_row = mysql_fetch_row(mail_res))) { - i++; + mysql_free_result(mail_res); + return 0; + } - if(!atoi(mail_row[5])) { + while ((mail_row = mysql_fetch_row(mail_res))) { + i++; + if(!atoi(mail_row[5])) { sprintf(tmp_msql,"UPDATE `%s` SET `check_flag`='1' WHERE `message_id`= \"%d\"", mail_db, atoi(mail_row[0])); - if(mysql_query(&mail_handle, tmp_msql) ) { - printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) ); - } + if(mysql_query(&mail_handle, tmp_msql) ) { + printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) ); } + } - if(!atoi(mail_row[3])) { - new++; - if(atoi(mail_row[4])) - priority++; - if(type==2 || type==3) { - if(atoi(mail_row[4])) { - sprintf(message, "%d - From : %s (New - Priority)", i, mail_row[2]); - clif_displaymessage(sd->fd, message); - } - - else { - sprintf(message, "%d - From : %s (New)", i, mail_row[2]); - clif_displaymessage(sd->fd, message); - } + if(!atoi(mail_row[3])) { + new_++; + if(atoi(mail_row[4])) + priority++; + if(type==2 || type==3) { + if(atoi(mail_row[4])) { + //sprintf(message, "%d - From : %s (New - Priority)", i, mail_row[2]); + sprintf(message, msg_txt(511), i, mail_row[2]); + + clif_displaymessage(sd->fd, jstrescape(message)); + } else { + //sprintf(message, "%d - From : %s (New)", i, mail_row[2]); + sprintf(message, msg_txt(512), i, mail_row[2]); + clif_displaymessage(sd->fd, jstrescape(message)); } } + } else if(type==2){ + //sprintf(message, "%d - From : %s", i, mail_row[2]); + sprintf(message, msg_txt(513), i, mail_row[2]); + clif_displaymessage(sd->fd, jstrescape(message)); + } + } - else if(type==2){ - sprintf(message, "%d - From : %s", i, mail_row[2]); - clif_displaymessage(sd->fd, message); - } - - } - mysql_free_result(mail_res); - } else { - printf("MySQL error (storing query result for %s): %s\n", mail_db, mysql_error(&mail_handle)); + printf("MySQL error (storing query result for %s): %s\n", mail_db, mysql_error(&mail_handle)); return 0; - } + } - if(i>0 && new>0 && type==1) { - sprintf(message, "You have %d new messages.", new); - clif_displaymessage(sd->fd, message); + if(i>0 && new_>0 && type==1) { + //sprintf(message, "You have %d new messages.", new_); + sprintf(message, msg_txt(514), new_); + + clif_displaymessage(sd->fd, jstrescape(message)); } - if(i>0 && new>0 && priority>0 && type==1) { - sprintf(message, "You have %d unread priority messages.", priority); - clif_displaymessage(sd->fd, message); + if(i>0 && new_>0 && priority>0 && type==1) { + //sprintf(message, "You have %d unread priority messages.", priority); + sprintf(message, msg_txt(515), priority); + clif_displaymessage(sd->fd, jstrescape(message)); } - if(!new) { - clif_displaymessage(sd->fd, "You have no new messages."); + if(!new_) { + //clif_displaymessage(sd->fd, "You have no new messages."); + clif_displaymessage(sd->fd, msg_txt(516)); } return 0; @@ -109,9 +117,8 @@ int mail_read(struct map_session_data *sd, int message_id) char message[80]; - if(sd==NULL) - return 0; - + nullpo_retr (0, sd); + sprintf(tmp_msql,"SELECT `message_id`,`to_account_id`,`from_char_name`,`message`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = \"%d\" ORDER by `message_id` LIMIT %d, 1",mail_db,sd->status.account_id,message_id-1); if (mysql_query(&mail_handle, tmp_msql)) { @@ -121,48 +128,47 @@ int mail_read(struct map_session_data *sd, int message_id) mail_res = mysql_store_result(&mail_handle); if(mail_res) { - if (mysql_num_rows(mail_res) == 0) { - mysql_free_result(mail_res); - clif_displaymessage(sd->fd, "Message not found."); - return 0; - } - - if ((mail_row = mysql_fetch_row(mail_res))) { + if (mysql_num_rows(mail_res) == 0) { + mysql_free_result(mail_res); + //clif_displaymessage(sd->fd, "Message not found."); + clif_displaymessage(sd->fd, msg_txt(517)); + return 0; + } + if ((mail_row = mysql_fetch_row(mail_res))) { if(!atoi(mail_row[6])) { sprintf(tmp_msql,"UPDATE `%s` SET `check_flag`='1' WHERE `message_id`= \"%d\"", mail_db, atoi(mail_row[0])); - if(mysql_query(&mail_handle, tmp_msql) ) { - printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) ); - } + if(mysql_query(&mail_handle, tmp_msql) ) { + printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) ); + } } - sprintf(message, "Reading message from %s", mail_row[2]); - clif_displaymessage(sd->fd, message); + //sprintf(message, "Reading message from %s", mail_row[2]); + sprintf(message, msg_txt(518), mail_row[2]); + clif_displaymessage(sd->fd, jstrescape(message)); sprintf(message, "%s", mail_row[3]); - clif_displaymessage(sd->fd, message); + clif_displaymessage(sd->fd, jstrescape(message)); sprintf(tmp_msql,"UPDATE `%s` SET `read_flag`='1' WHERE `message_id`= \"%d\"", mail_db, atoi(mail_row[0])); - if(mysql_query(&mail_handle, tmp_msql) ) { + if(mysql_query(&mail_handle, tmp_msql) ) { printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) ); - } + } } - + mysql_free_result(mail_res); - + } else { - printf("MySQL error (storing query result for %s): %s\n", mail_db, mysql_error(&mail_handle)); - return 0; - } + printf("MySQL error (storing query result for %s): %s\n", mail_db, mysql_error(&mail_handle)); + } return 0; } int mail_delete(struct map_session_data *sd, int message_id) { - if(sd==NULL) - return 0; - + nullpo_retr (0, sd); + sprintf(tmp_msql,"SELECT `message_id`,`to_account_id`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = \"%d\" ORDER by `message_id` LIMIT %d, 1",mail_db,sd->status.account_id,message_id-1); if (mysql_query(&mail_handle, tmp_msql)) { @@ -172,21 +178,25 @@ int mail_delete(struct map_session_data *sd, int message_id) mail_res = mysql_store_result(&mail_handle); if(mail_res) { - if (mysql_num_rows(mail_res) == 0) { - mysql_free_result(mail_res); - clif_displaymessage(sd->fd, "Message not found."); - return 0; - } + if (mysql_num_rows(mail_res) == 0) { + mysql_free_result(mail_res); + //clif_displaymessage(sd->fd, "Message not found."); + clif_displaymessage(sd->fd, msg_txt(517)); + return 0; + } - if ((mail_row = mysql_fetch_row(mail_res))) { + if ((mail_row = mysql_fetch_row(mail_res))) { if(!atoi(mail_row[2]) && atoi(mail_row[3])) { mysql_free_result(mail_res); - clif_displaymessage(sd->fd,"Cannot delete unread priority mail."); + //clif_displaymessage(sd->fd,"Cannot delete unread priority mail."); + clif_displaymessage(sd->fd,msg_txt(519)); + return 0; } if(!atoi(mail_row[4])) { mysql_free_result(mail_res); - clif_displaymessage(sd->fd,"You have recieved new mail, use @listmail before deleting."); + //clif_displaymessage(sd->fd,"You have recieved new mail, use @listmail before deleting."); + clif_displaymessage(sd->fd,msg_txt(520)); return 0; } sprintf(tmp_msql,"DELETE FROM `%s` WHERE `message_id` = \"%d\"", mail_db, atoi(mail_row[0])); @@ -195,75 +205,77 @@ int mail_delete(struct map_session_data *sd, int message_id) printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) ); return 0; } - else clif_displaymessage(sd->fd,"Message deleted."); + //else clif_displaymessage(sd->fd,"Message deleted."); + else clif_displaymessage(sd->fd,msg_txt(521)); } - + mysql_free_result(mail_res); - + } else { - printf("MySQL error (delete query result for %s): %s\n", mail_db, mysql_error(&mail_handle)); - return 0; - } + printf("MySQL error (delete query result for %s): %s\n", mail_db, mysql_error(&mail_handle)); + } return 0; } int mail_send(struct map_session_data *sd, char *name, char *message, int flag) { - if(sd==NULL) - return 0; - + nullpo_retr (0, sd); + if(pc_isGM(sd) < 80 && sd->mail_counter > 0) { - clif_displaymessage(sd->fd,"You must wait 10 minutes before sending another message"); + //clif_displaymessage(sd->fd,"You must wait 10 minutes before sending another message"); + clif_displaymessage(sd->fd,msg_txt(522)); return 0; } if(strcmp(name,"*")==0) { if(pc_isGM(sd) < 80) { - clif_displaymessage(sd->fd, "Access Denied."); + //clif_displaymessage(sd->fd, "Access Denied."); + clif_displaymessage(sd->fd, msg_txt(523)); return 0; } else sprintf(tmp_msql,"SELECT DISTINCT `account_id` FROM `%s` WHERE `account_id` <> '%d' ORDER BY `account_id`", char_db, sd->status.account_id); } else - sprintf(tmp_msql,"SELECT `account_id`,`name` FROM `%s` WHERE `name` = \"%s\"", char_db, name); + sprintf(tmp_msql,"SELECT `account_id`,`name` FROM `%s` WHERE `name` = \"%s\"", char_db, jstrescape(name)); if (mysql_query(&mail_handle, tmp_msql)) { printf("Database server error (executing query for %s): %s\n", char_db, mysql_error(&mail_handle)); return 0; - } - + } + mail_res = mysql_store_result(&mail_handle); if(mail_res) { - if (mysql_num_rows(mail_res) == 0) { + if (mysql_num_rows(mail_res) == 0) { mysql_free_result(mail_res); - clif_displaymessage(sd->fd,"Character does not exist."); - return 0; - } + //clif_displaymessage(sd->fd,"Character does not exist."); + clif_displaymessage(sd->fd,msg_txt(524)); + return 0; + } - while ((mail_row = mysql_fetch_row(mail_res))) { + while ((mail_row = mysql_fetch_row(mail_res))) { if(strcmp(name,"*")==0) { - sprintf(tmp_msql, "INSERT INTO `%s` (`to_account_id`,`from_account_id`,`from_char_name`,`message`,`priority`)" - " VALUES ('%d', '%d', '%s', '%s', '%d')",mail_db, atoi(mail_row[0]), sd->status.account_id, sd->status.name, message, flag); + sprintf(tmp_msql, "INSERT DELAYED INTO `%s` (`to_account_id`,`from_account_id`,`from_char_name`,`message`,`priority`)" + " VALUES ('%d', '%d', '%s', '%s', '%d')",mail_db, atoi(mail_row[0]), sd->status.account_id, sd->status.name, jstrescape(message), flag); } else { - sprintf(tmp_msql, "INSERT INTO `%s` (`to_account_id`,`to_char_name`,`from_account_id`,`from_char_name`,`message`,`priority`)" - " VALUES ('%d', '%s', '%d', '%s', '%s', '%d')",mail_db, atoi(mail_row[0]), mail_row[1], sd->status.account_id, sd->status.name, message, flag); + sprintf(tmp_msql, "INSERT DELAYED INTO `%s` (`to_account_id`,`to_char_name`,`from_account_id`,`from_char_name`,`message`,`priority`)" + " VALUES ('%d', '%s', '%d', '%s', '%s', '%d')",mail_db, atoi(mail_row[0]), mail_row[1], sd->status.account_id, sd->status.name, jstrescape(message), flag); if(pc_isGM(sd) < 80) sd->mail_counter=5; } - + if(mysql_query(&mail_handle, tmp_msql) ) { mysql_free_result(mail_res); printf("DB server Error (insert `mail_db`)- %s\n", mysql_error(&mail_handle) ); return 0; } - } } - clif_displaymessage(sd->fd,"Mail has been sent."); + //clif_displaymessage(sd->fd,"Mail has been sent."); + clif_displaymessage(sd->fd,msg_txt(525)); return 0; } @@ -271,43 +283,43 @@ int mail_send(struct map_session_data *sd, char *name, char *message, int flag) int mail_check_timer(int tid,unsigned int tick,int id,int data) { struct map_session_data *sd = NULL; - int i; + int i; if(mail_timer != tid) return 0; sprintf(tmp_msql,"SELECT DISTINCT `to_account_id` FROM `%s` WHERE `read_flag` = '0' AND `check_flag` = '0'", mail_db); - + if (mysql_query(&mail_handle, tmp_msql)) { printf("Database server error (executing query for %s): %s\n", char_db, mysql_error(&mail_handle)); mail_timer=add_timer(gettick()+MAIL_CHECK_TIME,mail_check_timer,0,0); return 0; - } + } mail_res = mysql_store_result(&mail_handle); if (mail_res) { - - if (mysql_num_rows(mail_res) == 0) { + if (mysql_num_rows(mail_res) == 0) { mysql_free_result(mail_res); mail_timer=add_timer(gettick()+MAIL_CHECK_TIME,mail_check_timer,0,0); - return 0; - } + return 0; + } - while ((mail_row = mysql_fetch_row(mail_res))) { + while ((mail_row = mysql_fetch_row(mail_res))) { for (i = 0; i < fd_max; i++) { - if (session[i] && (sd = session[i]->session_data) && sd->state.auth){ + if (session[i] && (sd = (struct map_session_data *) session[i]->session_data) && sd->state.auth){ if(pc_isGM(sd) < 80 && sd->mail_counter > 0) sd->mail_counter--; if(sd->status.account_id==atoi(mail_row[0])) - clif_displaymessage(sd->fd, "You have new mail."); + //clif_displaymessage(sd->fd, "You have new mail."); + clif_displaymessage(sd->fd, msg_txt(526)); } } } } sprintf(tmp_msql,"UPDATE `%s` SET `check_flag`='1' WHERE `check_flag`= '0' ", mail_db); - if(mysql_query(&mail_handle, tmp_msql) ) { + if(mysql_query(&mail_handle, tmp_msql) ) { printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) ); } @@ -316,9 +328,10 @@ int mail_check_timer(int tid,unsigned int tick,int id,int data) } int do_init_mail(void) -{ +{ add_timer_func_list(mail_check_timer,"mail_check_timer"); mail_timer=add_timer(gettick()+MAIL_CHECK_TIME,mail_check_timer,0,0); return 0; } +#endif diff --git a/src/map/map.c b/src/map/map.c index 3214373f9..386b38954 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -8,12 +8,14 @@ #else #include <netdb.h> #endif +#include <math.h> #include "core.h" #include "timer.h" #include "db.h" #include "grfio.h" #include "malloc.h" +#include "version.h" #include "map.h" #include "chrif.h" @@ -21,6 +23,7 @@ #include "intif.h" #include "npc.h" #include "pc.h" +#include "status.h" #include "mob.h" #include "chat.h" #include "itemdb.h" @@ -43,7 +46,8 @@ #include "memwatch.h" #endif -unsigned long ticks = 0; // by MC Cameri +// maybe put basic macros to somewhere else +#define swap(a,b) ((a == b) || ((a ^= b), (b ^= a), (a ^= b))) #ifndef TXT_ONLY @@ -99,19 +103,31 @@ int read_gm_interval = 600000; char char_db[32] = "char"; static int online_timer(int,unsigned int,int,int); - int CHECK_INTERVAL = 3600000; // [Valaris] -int check_online_timer=0; // [Valaris] #endif /* not TXT_ONLY */ -// ‹É—Í static‚Ń[ƒJƒ‹‚ÉŽû‚ß‚é + +char *INTER_CONF_NAME; +char *LOG_CONF_NAME; +char *MAP_CONF_NAME; +char *BATTLE_CONF_FILENAME; +char *ATCOMMAND_CONF_FILENAME; +char *CHARCOMMAND_CONF_FILENAME; +char *SCRIPT_CONF_NAME; +char *MSG_CONF_NAME; +char *GRF_PATH_FILENAME; + +#define USE_AFM +#define USE_AF2 + +// ‹É—Í static‚Ń?ƒJƒ‹‚É?‚ß‚é static struct dbt * id_db=NULL; static struct dbt * map_db=NULL; static struct dbt * nick_db=NULL; static struct dbt * charid_db=NULL; static int users=0; -static struct block_list *object[MAX_FLOORITEM]; +static struct block_list *objects[MAX_FLOORITEM]; static int first_free_object_id=0,last_object_id=0; #define block_free_max 1048576 @@ -145,23 +161,33 @@ struct charid2nick { int req_id; }; +// «Þ«Ã«×««ã«Ã«·«å××éīի髰(map_athana.conf?ªÎread_map_from_cacheªÇò¦E) +// 0:××éĪ·ªÊª¤ 1:Þª?õêÜÁðí 2:?õêÜÁðí +int map_read_flag = READ_FROM_GAT; +char map_cache_file[256]="db/map.info"; // «Þ«Ã«×««ã«Ã«·«å«Õ«¡«¤«E£ + char motd_txt[256] = "conf/motd.txt"; char help_txt[256] = "conf/help.txt"; char wisp_server_name[24] = "Server"; // can be modified in char-server configuration file int console = 0; + /*========================================== - * ‘SmapŽI‘Œv‚Å‚ÌÚ‘±”Ý’è + * ‘SmapŽI?Œv‚Å‚ÌÚ??Ý’è * (charŽI‚©‚ç‘—‚ç‚ê‚Ä‚‚é) *------------------------------------------ */ -void map_setusers(int n) { - users = n; +void map_setusers(int fd) +{ + users = RFIFOL(fd,2); + // send some anser + WFIFOW(fd,0) = 0x2718; + WFIFOSET(fd,2); } /*========================================== - * ‘SmapŽI‘Œv‚Å‚ÌÚ‘±”Žæ“¾ (/w‚ւ̉ž“š—p) + * ‘SmapŽI?Œv‚Å‚ÌÚ??Žæ“¾ (/w‚Ö‚Ì?“š—p) *------------------------------------------ */ int map_getusers(void) { @@ -169,18 +195,18 @@ int map_getusers(void) { } // -// block휂̈À‘S«Šm•Ûˆ— +// block휂̈À‘S«Šm•Û?— // /*========================================== - * block‚ðfree‚·‚邯‚«free‚̕ςí‚è‚ÉŒÄ‚Ô + * block‚ðfree‚·‚邯‚«free‚Ì?‚í‚è‚ÉŒÄ‚Ô * ƒƒbƒN‚³‚ê‚Ä‚¢‚邯‚«‚̓oƒbƒtƒ@‚É‚½‚ß‚é *------------------------------------------ */ int map_freeblock( void *bl ) { if(block_free_lock==0){ - free(bl); + aFree(bl); bl = NULL; } else{ @@ -216,23 +242,40 @@ int map_freeblock_unlock(void) { // printf("map_freeblock_unlock: free %d object\n",block_free_count); // } for(i=0;i<block_free_count;i++){ - free(block_free[i]); + aFree(block_free[i]); block_free[i] = NULL; } block_free_count=0; }else if(block_free_lock<0){ if(battle_config.error_log) printf("map_freeblock_unlock: lock count < 0 !\n"); + block_free_lock = 0; // ŽŸ‰ñˆÈ~‚̃ƒbƒN‚ÉŽxႪo‚Ä‚‚é‚Ì‚ÅƒŠƒZƒbƒg } return block_free_lock; } +// map_freeblock_lock() ‚ðŒÄ‚ñ‚Å map_freeblock_unlock() ‚ðŒÄ‚΂Ȃ¢ +// ŠÖ”‚ª‚ ‚Á‚½‚Ì‚ÅA’èŠú“I‚Éblock_free_lock‚ðƒŠƒZƒbƒg‚·‚邿‚¤‚É‚·‚éB +// ‚±‚ÌŠÖ”‚ÍAdo_timer() ‚̃gƒbƒvƒŒƒxƒ‹‚©‚çŒÄ‚΂ê‚é‚Ì‚ÅA +// block_free_lock ‚ð’¼Ú‚¢‚¶‚Á‚Ä‚àŽxá–³‚¢‚Í‚¸B + +int map_freeblock_timer(int tid,unsigned int tick,int id,int data) { + if(block_free_lock > 0) { + printf("map_freeblock_timer: block_free_lock(%d) is invalid.\n",block_free_lock); + block_free_lock = 1; + map_freeblock_unlock(); + } + // else { + // printf("map_freeblock_timer: check ok\n"); + // } + return 0; +} // -// block‰»ˆ— +// block‰»?— // /*========================================== - * map[]‚Ìblock_list‚©‚çŒq‚ª‚Á‚Ä‚¢‚éê‡‚É + * map[]‚Ìblock_list‚©‚ç?‚ª‚Á‚Ä‚¢‚éê‡‚É * bl->prev‚Ébl_head‚̃AƒhƒŒƒX‚ð“ü‚ê‚Ä‚¨‚ *------------------------------------------ */ @@ -240,9 +283,9 @@ static struct block_list bl_head; /*========================================== * map[]‚Ìblock_list‚ɒljÁ - * mob‚Í”‚ª‘½‚¢‚Ì‚Å•ÊƒŠƒXƒg + * mob‚Í?‚ª‘½‚¢‚Ì‚Å•ÊƒŠƒXƒg * - * Šù‚Élinkς݂©‚ÌŠm”F‚ª–³‚¢BŠëŒ¯‚©‚à + * ?‚Élink?‚Ý‚©‚ÌŠm”F‚ª–³‚¢BŠë?‚©‚à *------------------------------------------ */ int map_addblock(struct block_list *bl) @@ -286,7 +329,7 @@ int map_addblock(struct block_list *bl) /*========================================== * map[]‚Ìblock_list‚©‚çŠO‚· - * prev‚ªNULL‚Ìê‡list‚ÉŒq‚ª‚Á‚ĂȂ¢ + * prev‚ªNULL‚Ìê‡list‚É?‚ª‚Á‚ĂȂ¢ *------------------------------------------ */ int map_delblock(struct block_list *bl) @@ -294,7 +337,7 @@ int map_delblock(struct block_list *bl) int b; nullpo_retr(0, bl); - // Šù‚Éblocklist‚©‚甲‚¯‚Ä‚¢‚é + // ?‚Éblocklist‚©‚ç?‚¯‚Ä‚¢‚é if(bl->prev==NULL){ if(bl->next!=NULL){ // prev‚ªNULL‚Ånext‚ªNULL‚łȂ¢‚̂͗L‚Á‚Ă͂Ȃç‚È‚¢ @@ -308,7 +351,8 @@ int map_delblock(struct block_list *bl) if(bl->type==BL_PC) map[bl->m].users--; - if(bl->next) bl->next->prev = bl->prev; + if(bl->next) + bl->next->prev = bl->prev; if(bl->prev==&bl_head){ // ƒŠƒXƒg‚Ì“ª‚Ȃ̂ÅAmap[]‚Ìblock_list‚ðXV‚·‚é if(bl->type==BL_MOB){ @@ -330,7 +374,7 @@ int map_delblock(struct block_list *bl) } /*========================================== - * ŽüˆÍ‚ÌPCl”‚𔂦‚é (Œ»Ý–¢Žg—p) + * Žü?‚ÌPCl?‚ð?‚¦‚é (Œ»Ý–¢Žg—p) *------------------------------------------ */ int map_countnearpc(int m, int x, int y) { @@ -356,7 +400,7 @@ int map_countnearpc(int m, int x, int y) { } /*========================================== - * ƒZƒ‹ã‚ÌPC‚ÆMOB‚Ì”‚𔂦‚é (ƒOƒ‰ƒ“ƒhƒNƒƒX—p) + * ƒZƒ‹ã‚ÌPC‚ÆMOB‚Ì?‚ð?‚¦‚é (ƒOƒ‰ƒ“ƒhƒNƒƒX—p) *------------------------------------------ */ int map_count_oncell(int m, int x, int y) { @@ -383,18 +427,47 @@ int map_count_oncell(int m, int x, int y) { if(!count) count = 1; return count; } +/* + * «»«E¾ªÎõÌôøªË̸ªÄª±ª¿«¹««Eæ«Ë«Ã«ÈªòÚ÷ª¹ + */ +struct skill_unit *map_find_skill_unit_oncell(struct block_list *target,int x,int y,int skill_id,struct skill_unit *out_unit) +{ + int m,bx,by; + struct block_list *bl; + int i,c; + struct skill_unit *unit; + m = target->m; + if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys)) + return NULL; + bx = x/BLOCK_SIZE; + by = y/BLOCK_SIZE; + + bl = map[m].block[bx+by*map[m].bxs]; + c = map[m].block_count[bx+by*map[m].bxs]; + for(i=0;i<c && bl;i++,bl=bl->next){ + if (bl->x != x || bl->y != y || bl->type != BL_SKILL) + continue; + unit = (struct skill_unit *) bl; + if (unit==out_unit || !unit->alive || + !unit->group || unit->group->skill_id!=skill_id) + continue; + if (battle_check_target(&unit->bl,target,unit->group->target_flag)>0) + return unit; + } + return NULL; +} /*========================================== - * map m (x0,y0)-(x1,y1)“à‚Ì‘Sobj‚ɑ΂µ‚Ä + * map m (x0,y0)-(x1,y1)?‚Ì‘Sobj‚É?‚µ‚Ä * func‚ðŒÄ‚Ô * type!=0 ‚Ȃ炻‚ÌŽí—Þ‚Ì‚Ý *------------------------------------------ */ void map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int type,...) { + va_list ap; int bx,by; struct block_list *bl=NULL; - va_list ap=NULL; int blockcount=bl_list_count,i,c; if(m < 0) @@ -437,7 +510,7 @@ void map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int map_freeblock_lock(); // ƒƒ‚ƒŠ‚©‚ç‚̉ð•ú‚ð‹ÖŽ~‚·‚é for(i=blockcount;i<bl_list_count;i++) - if(bl_list[i]->prev) // —LŒø‚©‚Ç‚¤‚©ƒ`ƒFƒbƒN + if(bl_list[i]->prev) // —L?‚©‚Ç‚¤‚©ƒ`ƒFƒbƒN func(bl_list[i],ap); map_freeblock_unlock(); // ‰ð•ú‚ð‹–‰Â‚·‚é @@ -448,8 +521,8 @@ void map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int /*========================================== * ‹éŒ`(x0,y0)-(x1,y1)‚ª(dx,dy)ˆÚ“®‚µ‚½Žž‚Ì - * —̈æŠO‚ɂȂé—̈æ(‹éŒ`‚©LŽšŒ`)“à‚Ìobj‚É - * ‘΂µ‚Äfunc‚ðŒÄ‚Ô + * —̈æŠO‚ɂȂé—̈æ(‹éŒ`‚©LŽšŒ`)?‚Ìobj‚É + * ?‚µ‚Äfunc‚ðŒÄ‚Ô * * dx,dy‚Í-1,0,1‚݂̂Ƃ·‚éi‚Ç‚ñ‚È’l‚Å‚à‚¢‚¢‚Á‚Û‚¢Hj *------------------------------------------ @@ -457,7 +530,7 @@ void map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int void map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int dx,int dy,int type,...) { int bx,by; struct block_list *bl=NULL; - va_list ap=NULL; + va_list ap; int blockcount=bl_list_count,i,c; va_start(ap,type); @@ -546,8 +619,12 @@ void map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0, map_freeblock_lock(); // ƒƒ‚ƒŠ‚©‚ç‚̉ð•ú‚ð‹ÖŽ~‚·‚é for(i=blockcount;i<bl_list_count;i++) - if(bl_list[i]->prev) // —LŒø‚©‚Ç‚¤‚©ƒ`ƒFƒbƒN + if(bl_list[i]->prev) { // —L?‚©‚Ç‚¤‚©ƒ`ƒFƒbƒN + if (bl_list[i]->type == BL_PC + && session[((struct map_session_data *) bl_list[i])->fd] == NULL) + continue; func(bl_list[i],ap); + } map_freeblock_unlock(); // ‰ð•ú‚ð‹–‰Â‚·‚é @@ -562,7 +639,7 @@ void map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0, void map_foreachincell(int (*func)(struct block_list*,va_list),int m,int x,int y,int type,...) { int bx,by; struct block_list *bl=NULL; - va_list ap=NULL; + va_list ap; int blockcount=bl_list_count,i,c; va_start(ap,type); @@ -602,18 +679,445 @@ void map_foreachincell(int (*func)(struct block_list*,va_list),int m,int x,int y map_freeblock_lock(); // ƒƒ‚ƒŠ‚©‚ç‚̉ð•ú‚ð‹ÖŽ~‚·‚é for(i=blockcount;i<bl_list_count;i++) - if(bl_list[i]->prev) // —LŒø‚©‚Ç‚¤‚©ƒ`ƒFƒbƒN + if(bl_list[i]->prev) // —L?‚©‚Ç‚¤‚©ƒ`ƒFƒbƒN + func(bl_list[i],ap); + + map_freeblock_unlock(); // ‰ð•ú‚ð‹–‰Â‚·‚é + + va_end(ap); + bl_list_count = blockcount; +} + +/*============================================================ +* For checking a path between two points (x0, y0) and (x1, y1) +*------------------------------------------------------------ + */ +void map_foreachinpath(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int range,int type,...) +{ +/* va_list ap; + double deltax = 0.0; + double deltay = 0.0; + int t, bx, by; + int *xs, *ys; + int blockcount = bl_list_count, i, c; + struct block_list *bl = NULL; + + if(m < 0) + return; + va_start(ap,type); + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (x1 >= map[m].xs) x1 = map[m].xs-1; + if (y1 >= map[m].ys) y1 = map[m].ys-1; + + // I'm not finished thinking on it + // but first it might better use a parameter equation + // x=(x1-x0)*t+x0; y=(y1-y0)*t+y0; t=[0,1] + // would not need special case aproximating for infinity/zero slope + // so maybe this way: + + // find maximum runindex + int tmax = abs(y1-y0); + if(tmax < abs(x1-x0)) + tmax = abs(x1-x0); + + xs = (int *)aCallocA(tmax + 1, sizeof(int)); + ys = (int *)aCallocA(tmax + 1, sizeof(int)); + + // pre-calculate delta values for x and y destination + // should speed up cause you don't need to divide in the loop + if(tmax>0) + { + deltax = ((double)(x1-x0)) / ((double)tmax); + deltay = ((double)(y1-y0)) / ((double)tmax); + } + // go along the index + for(t=0; t<=tmax; t++) + { + int x = (int)floor(deltax * (double)t +0.5)+x0; + int y = (int)floor(deltay * (double)t +0.5)+y0; + // the xy pairs of points in line between x0y0 and x1y1 + // including start and end point + xs[t] = x; + ys[t] = y; + } + + if (type == 0 || type != BL_MOB) + + +this here is wrong, +there is no check if x0<x1 and y0<y1 +but this is not valid in 3 of 4 cases, +so in this case here you check only blocks when shooting to a positive direction +shooting in other directions just do nothing like the skill has failed +if you want to keep this that way then check and swap x0,y0 with x1,y1 + + for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { + for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){ + bl = map[m].block[bx+by*map[m].bxs]; + c = map[m].block_count[bx+by*map[m].bxs]; + for(i=0;i<c && bl;i++,bl=bl->next){ + if(bl) { + if (type && bl->type!=type) + continue; + for(t=0; t<=tmax; t++) + if(bl->x==xs[t] && bl->y==ys[t] && bl_list_count<BL_LIST_MAX) + bl_list[bl_list_count++]=bl; + } + } + } + } + if(type==0 || type==BL_MOB) + for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){ + for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){ + bl = map[m].block_mob[bx+by*map[m].bxs]; + c = map[m].block_mob_count[bx+by*map[m].bxs]; + for(i=0;i<c && bl;i++,bl=bl->next){ + if(bl) { + for(t=0; t<=tmax; t++) + if(bl->x==xs[t] && bl->y==ys[t] && bl_list_count<BL_LIST_MAX) + bl_list[bl_list_count++]=bl; + } + } + } + } + + if(bl_list_count>=BL_LIST_MAX) { + if(battle_config.error_log) + printf("map_foreachinarea: *WARNING* block count too many!\n"); + } + + map_freeblock_lock(); // ƒƒ‚ƒŠ‚©‚ç‚̉ð•ú‚ð‹ÖŽ~‚·‚é + + for(i=blockcount;i<bl_list_count;i++) + if(bl_list[i]->prev) // —L?‚©‚Ç‚¤‚©ƒ`ƒFƒbƒN func(bl_list[i],ap); map_freeblock_unlock(); // ‰ð•ú‚ð‹–‰Â‚·‚é + bl_list_count = blockcount; + aFree (xs); + aFree (ys); + va_end(ap); + +*/ + +/* +////////////////////////////////////////////////////////////// +// +// sharp shooting 1 +// +////////////////////////////////////////////////////////////// +// problem: +// finding targets standing on and within some range of a line +// (t1,t2 t3 and t4 get hit) +// +// target 1 +// x t4 +// t2 +// t3 x +// x +// S +////////////////////////////////////////////////////////////// +// solution 1 (straight forward, but a bit calculation expensive) +// calculating perpendiculars from quesionable mobs to the straight line +// if the mob is hit then depends on the distance to the line +// +// solution 2 (complex, need to handle many cases, but maybe faster) +// make a formula to deside if a given (x,y) is within a shooting area +// the shape can be ie. rectangular or triangular +// if the mob is hit then depends on if the mob is inside or outside the area +// I'm not going to implement this, but if somebody is interested +// in vector algebra, it might be some fun + +////////////////////////////////////////////////////////////// +// possible shooting ranges (I prefer the second one) +////////////////////////////////////////////////////////////// +// +// ---------------- ------ +// ---------------- ------------ +// Sxxxxxxxxxxxxxxxxtarget Sxxxxxxxxxxxxxxxxtarget +// ---------------- ------------ +// ---------------- ----- +// +// the original code implemented the left structure +// might be not that realistic, so I changed to the other one +// I take "range" as max distance from the line +////////////////////////////////////////////////////////////// + + va_list ap; + int i, blockcount = bl_list_count; + struct block_list *bl; + int c1,c2; + +/////////// + double deltax,deltay; + double k,kfact,knorm; + double v1,v2,distance; + double xm,ym,rd; + int bx,by,bx0,bx1,by0,by1; +////////////// + // no map + if(m < 0) return; + + // xy out of range + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (x1 >= map[m].xs) x1 = map[m].xs-1; + if (y1 >= map[m].ys) y1 = map[m].ys-1; + + /////////////////////////////// + // stuff for a linear equation in xy coord to calculate + // the perpendicular from a block xy to the straight line + deltax = (x1-x0); + deltay = (y1-y0); + kfact = (deltax*deltax+deltay*deltay); // the sqare length of the line + knorm = -deltax*x0-deltay*y0; // the offset vector param + +//printf("(%i,%i)(%i,%i) range: %i\n",x0,y0,x1,y1,range); + + if(kfact==0) return; // shooting at the standing position should not happen + kfact = 1/kfact; // divide here and multiply in the loop + + range *= range; // compare with range^2 so we can skip a sqrt and signs + + /////////////////////////////// + // prepare shooting area check + xm = (x1+x0)/2.0; + ym = (y1+y0)/2.0;// middle point on the shooting line + // the sqared radius of a circle around the shooting range + // plus the sqared radius of a block + rd = (x0-xm)*(x0-xm) + (y0-ym)*(y0-ym) + (range*range) + +BLOCK_SIZE*BLOCK_SIZE/2; + // so whenever a block midpoint is within this circle + // some of the block area is possibly within the shooting range + + /////////////////////////////// + // what blocks we need to test + // blocks covered by the xy position of begin and end of the line + bx0 = x0/BLOCK_SIZE; + bx1 = x1/BLOCK_SIZE; + by0 = y0/BLOCK_SIZE; + by1 = y1/BLOCK_SIZE; + // swap'em for a smallest-to-biggest run + if(bx0>bx1) swap(bx0,bx1); + if(by0>by1) swap(by0,by1); + + // enlarge the block area by a range value and 1 + // so we can be sure to process all blocks that might touch the shooting area + // in this case here with BLOCK_SIZE=8 and range=2 it will be only enlarged by 1 + // but I implement it anyway just in case that ranges will be larger + // or BLOCK_SIZE smaller in future + i = (range/BLOCK_SIZE+1);//temp value + if(bx0>i) bx0 -=i; else bx0=0; + if(by0>i) by0 -=i; else by0=0; + if(bx1+i<map[m].bxs) bx1 +=i; else bx1=map[m].bxs-1; + if(by1+i<map[m].bys) by1 +=i; else by1=map[m].bys-1; + + +//printf("run for (%i,%i)(%i,%i)\n",bx0,by0,bx1,by1); + for(bx=bx0; bx<=bx1; bx++) + for(by=by0; by<=by1; by++) + { // block xy + c1 = map[m].block_count[bx+by*map[m].bxs]; // number of elements in the block + c2 = map[m].block_mob_count[bx+by*map[m].bxs]; // number of mobs in the mob block + if( (c1==0) && (c2==0) ) continue; // skip if nothing in the blocks + +//printf("block(%i,%i) %i %i\n",bx,by,c1,c2);fflush(stdout); + // test if the mid-point of the block is too far away + // so we could skip the whole block in this case + v1 = (bx*BLOCK_SIZE+BLOCK_SIZE/2-xm)*(bx*BLOCK_SIZE+BLOCK_SIZE/2-xm) + +(by*BLOCK_SIZE+BLOCK_SIZE/2-ym)*(by*BLOCK_SIZE+BLOCK_SIZE/2-ym); +//printf("block(%i,%i) v1=%f rd=%f\n",bx,by,v1,rd);fflush(stdout); + // check for the worst case scenario + if(v1 > rd) continue; + + // it seems that the block is at least partially covered by the shooting range + // so we go into it + if(type==0 || type!=BL_MOB) { + bl = map[m].block[bx+by*map[m].bxs]; // a block with the elements + for(i=0;i<c1 && bl;i++,bl=bl->next){ // go through all elements + if( bl && ( !type || bl->type==type ) && bl_list_count<BL_LIST_MAX ) + { + // calculate the perpendicular from block xy to the straight line + k = kfact*(deltax*bl->x + deltay*bl->y + knorm); + // check if the perpendicular is within start and end of our line + if(k>=0 && k<=1) + { // calculate the distance + v1 = deltax*k+x0 - bl->x; + v2 = deltay*k+y0 - bl->y; + distance = v1*v1+v2*v2; + // triangular shooting range + if( distance <= range*k ) + bl_list[bl_list_count++]=bl; + } + } + }//end for elements + } + + if(type==0 || type==BL_MOB) { + bl = map[m].block_mob[bx+by*map[m].bxs]; // and the mob block + for(i=0;i<c2 && bl;i++,bl=bl->next){ + if(bl && bl_list_count<BL_LIST_MAX) { + // calculate the perpendicular from block xy to the straight line + k = kfact*(deltax*bl->x + deltay*bl->y + knorm); +//printf("mob: (%i,%i) k=%f ",bl->x,bl->y, k); + // check if the perpendicular is within start and end of our line + if(k>=0 && k<=1) + { + v1 = deltax*k+x0 - bl->x; + v2 = deltay*k+y0 - bl->y; + distance = v1*v1+v2*v2; +//printf("dist: %f",distance); + // triangular shooting range + if( distance <= range*k ) + { +//printf(" hit"); + bl_list[bl_list_count++]=bl; + } + } +//printf("\n"); + } + }//end for mobs + } + }//end for(bx,by) + + + if(bl_list_count>=BL_LIST_MAX) { + if(battle_config.error_log) + printf("map_foreachinarea: *WARNING* block count too many!\n"); + } + + va_start(ap,type); + map_freeblock_lock(); // ƒƒ‚ƒŠ‚©‚ç‚̉ð•ú‚ð‹ÖŽ~‚·‚é + + for(i=blockcount;i<bl_list_count;i++) + if(bl_list[i]->prev) // —L?‚©‚Ç‚¤‚©ƒ`ƒFƒbƒN + func(bl_list[i],ap); + + map_freeblock_unlock(); // ‰ð•ú‚ð‹–‰Â‚·‚é + va_end(ap); + + bl_list_count = blockcount; + +*/ + + +////////////////////////////////////////////////////////////// +// +// sharp shooting 2 +// +////////////////////////////////////////////////////////////// +// problem: +// finding targets standing exactly on a line +// (only t1 and t2 get hit) +// +// target 1 +// x t4 +// t2 +// t3 x +// x +// S +////////////////////////////////////////////////////////////// + va_list ap; + int i, blockcount = bl_list_count; + struct block_list *bl; + int c1,c2; + + ////////////////////////////////////////////////////////////// + // linear parametric equation + // x=(x1-x0)*t+x0; y=(y1-y0)*t+y0; t=[0,1] + ////////////////////////////////////////////////////////////// + // linear equation for finding a single line between (x0,y0)->(x1,y1) + // independent of the given xy-values + double dx = 0.0; + double dy = 0.0; + int bx=-1; // initialize block coords to some impossible value + int by=-1; + + int t; + /////////////////////////////// + // find maximum runindex + int tmax = abs(y1-y0); + if(tmax < abs(x1-x0)) + tmax = abs(x1-x0); + // pre-calculate delta values for x and y destination + // should speed up cause you don't need to divide in the loop + if(tmax>0) + { + dx = ((double)(x1-x0)) / ((double)tmax); + dy = ((double)(y1-y0)) / ((double)tmax); + } + // go along the index + for(t=0; t<=tmax; t++) + { // xy-values of the line including start and end point + int x = (int)floor(dx * (double)t +0.5)+x0; + int y = (int)floor(dy * (double)t +0.5)+y0; + + // check the block index of the calculated xy + if( (bx!=x/BLOCK_SIZE) || (by!=y/BLOCK_SIZE) ) + { // we have reached a new block + // so we store the current block coordinates + bx = x/BLOCK_SIZE; + by = y/BLOCK_SIZE; + + // and process the data + c1 = map[m].block_count[bx+by*map[m].bxs]; // number of elements in the block + c2 = map[m].block_mob_count[bx+by*map[m].bxs]; // number of mobs in the mob block + if( (c1==0) && (c2==0) ) continue; // skip if nothing in the block + + if(type==0 || type!=BL_MOB) { + bl = map[m].block[bx+by*map[m].bxs]; // a block with the elements + for(i=0;i<c1 && bl;i++,bl=bl->next){ // go through all elements + if( bl && ( !type || bl->type==type ) && bl_list_count<BL_LIST_MAX ) + { + // check if block xy is on the line + if( (bl->x-x0)*(y1-y0) == (bl->y-y0)*(x1-x0) ) + // and if it is within start and end point + if( (((x0<=x1)&&(x0<=bl->x)&&(bl->x<=x1)) || ((x0>=x1)&&(x0>=bl->x)&&(bl->x>=x1))) && + (((y0<=y1)&&(y0<=bl->y)&&(bl->y<=y1)) || ((y0>=y1)&&(y0>=bl->y)&&(bl->y>=y1))) ) + bl_list[bl_list_count++]=bl; + } + }//end for elements + } + + if(type==0 || type==BL_MOB) { + bl = map[m].block_mob[bx+by*map[m].bxs]; // and the mob block + for(i=0;i<c2 && bl;i++,bl=bl->next){ + if(bl && bl_list_count<BL_LIST_MAX) { + // check if mob xy is on the line + if( (bl->x-x0)*(y1-y0) == (bl->y-y0)*(x1-x0) ) + // and if it is within start and end point + if( (((x0<=x1)&&(x0<=bl->x)&&(bl->x<=x1)) || ((x0>=x1)&&(x0>=bl->x)&&(bl->x>=x1))) && + (((y0<=y1)&&(y0<=bl->y)&&(bl->y<=y1)) || ((y0>=y1)&&(y0>=bl->y)&&(bl->y>=y1))) ) + bl_list[bl_list_count++]=bl; + } + }//end for mobs + } + } + }//end for index + + if(bl_list_count>=BL_LIST_MAX) { + if(battle_config.error_log) + printf("map_foreachinarea: *WARNING* block count too many!\n"); + } + + va_start(ap,type); + map_freeblock_lock(); // ƒƒ‚ƒŠ‚©‚ç‚̉ð•ú‚ð‹ÖŽ~‚·‚é + + for(i=blockcount;i<bl_list_count;i++) + if(bl_list[i]->prev) // —L?‚©‚Ç‚¤‚©ƒ`ƒFƒbƒN + func(bl_list[i],ap); + + map_freeblock_unlock(); // ‰ð•ú‚ð‹–‰Â‚·‚é va_end(ap); + bl_list_count = blockcount; } /*========================================== - * °ƒAƒCƒeƒ€‚âƒGƒtƒFƒNƒg—p‚̈ꎞobjŠ„‚è“–‚Ä - * object[]‚ւ̕ۑ¶‚Æid_db“o˜^‚܂Š+ * °ƒAƒCƒeƒ€‚âƒGƒtƒFƒNƒg—p‚̈ꎞobjŠ„‚è?‚Ä + * object[]‚ւ̕ۑ¶‚Æid_db“o?‚܂Š* * bl->id‚à‚±‚Ì’†‚Åݒ肵‚Ä–â‘è–³‚¢? *------------------------------------------ @@ -627,7 +1131,7 @@ int map_addobject(struct block_list *bl) { if(first_free_object_id<2 || first_free_object_id>=MAX_FLOORITEM) first_free_object_id=2; for(i=first_free_object_id;i<MAX_FLOORITEM;i++) - if(object[i]==NULL) + if(objects[i]==NULL) break; if(i>=MAX_FLOORITEM){ if(battle_config.error_log) @@ -637,29 +1141,29 @@ int map_addobject(struct block_list *bl) { first_free_object_id=i; if(last_object_id<i) last_object_id=i; - object[i]=bl; + objects[i]=bl; numdb_insert(id_db,i,bl); return i; } /*========================================== * ˆêŽžobject‚̉ð•ú - * map_delobject‚Ìfree‚µ‚È‚¢ƒo[ƒWƒ‡ƒ“ + * map_delobject‚Ìfree‚µ‚È‚¢ƒo?ƒWƒ‡ƒ“ *------------------------------------------ */ int map_delobjectnofree(int id) { - if(object[id]==NULL) + if(objects[id]==NULL) return 0; - map_delblock(object[id]); + map_delblock(objects[id]); numdb_erase(id_db,id); -// map_freeblock(object[id]); - object[id]=NULL; +// map_freeblock(objects[id]); + objects[id]=NULL; if(first_free_object_id>id) first_free_object_id=id; - while(last_object_id>2 && object[last_object_id]==NULL) + while(last_object_id>2 && objects[last_object_id]==NULL) last_object_id--; return 0; @@ -670,11 +1174,11 @@ int map_delobjectnofree(int id) { * block_list‚©‚ç‚ÌíœAid_db‚©‚ç‚Ìíœ * object data‚ÌfreeAobject[]‚Ö‚ÌNULL‘ã“ü * - * add‚Ƃ̑ÎÌ«‚ª–³‚¢‚Ì‚ª‹C‚ɂȂé + * add‚Æ‚Ì??«‚ª–³‚¢‚Ì‚ª?‚ɂȂé *------------------------------------------ */ int map_delobject(int id) { - struct block_list *obj = object[id]; + struct block_list *obj = objects[id]; if(obj==NULL) return 0; @@ -693,20 +1197,20 @@ int map_delobject(int id) { void map_foreachobject(int (*func)(struct block_list*,va_list),int type,...) { int i; int blockcount=bl_list_count; - va_list ap=NULL; + va_list ap; va_start(ap,type); for(i=2;i<=last_object_id;i++){ - if(object[i]){ - if(type && object[i]->type!=type) + if(objects[i]){ + if(type && objects[i]->type!=type) continue; if(bl_list_count>=BL_LIST_MAX) { if(battle_config.error_log) printf("map_foreachobject: too many block !\n"); } else - bl_list[bl_list_count++]=object[i]; + bl_list[bl_list_count++]=objects[i]; } } @@ -729,13 +1233,13 @@ void map_foreachobject(int (*func)(struct block_list*,va_list),int type,...) { * data!=0‚ÌŽž‚ÍE‚¤“™‚ÅÁ‚¦‚½Žž‚Æ‚µ‚Ä“®ì * * ŒãŽÒ‚ÍAmap_clearflooritem(id)‚Ö - * map.h“à‚Å#define‚µ‚Ä‚ ‚é + * map.h?‚Å#define‚µ‚Ä‚ ‚é *------------------------------------------ */ int map_clearflooritem_timer(int tid,unsigned int tick,int id,int data) { struct flooritem_data *fitem=NULL; - fitem = (struct flooritem_data *)object[id]; + fitem = (struct flooritem_data *)objects[id]; if(fitem==NULL || fitem->bl.type!=BL_ITEM || (!data && fitem->cleartimer != tid)){ if(battle_config.error_log) printf("map_clearflooritem_timer : error\n"); @@ -752,14 +1256,14 @@ int map_clearflooritem_timer(int tid,unsigned int tick,int id,int data) { } /*========================================== - * (m,x,y)‚ÌŽüˆÍrangeƒ}ƒX“à‚Ì‹ó‚«(=N“ü‰Â”\)cell‚Ì - * “à‚©‚ç“K“–‚ȃ}ƒX–Ú‚ÌÀ•W‚ðx+(y<<16)‚ŕԂ· + * (m,x,y)‚ÌŽü?rangeƒ}ƒX?‚Ì‹ó‚«(=N“ü‰Â”\)cell‚Ì + * ?‚©‚ç“K?‚ȃ}ƒX–Ú‚ÌÀ•W‚ðx+(y<<16)‚ŕԂ· * - * Œ»órange=1‚ŃAƒCƒeƒ€ƒhƒƒbƒv—p“r‚Ì‚Ý + * Œ»?range=1‚ŃAƒCƒeƒ€ƒhƒƒbƒv—p“r‚Ì‚Ý *------------------------------------------ */ int map_searchrandfreecell(int m,int x,int y,int range) { - int free_cell,i,j,c; + int free_cell,i,j; for(free_cell=0,i=-range;i<=range;i++){ if(i+y<0 || i+y>=map[m].ys) @@ -767,7 +1271,7 @@ int map_searchrandfreecell(int m,int x,int y,int range) { for(j=-range;j<=range;j++){ if(j+x<0 || j+x>=map[m].xs) continue; - if((c=read_gat(m,j+x,i+y))==1 || c==5) + if(map_getcell(m,j+x,i+y,CELL_CHKNOPASS)) continue; free_cell++; } @@ -781,7 +1285,7 @@ int map_searchrandfreecell(int m,int x,int y,int range) { for(j=-range;j<=range;j++){ if(j+x<0 || j+x>=map[m].xs) continue; - if((c=read_gat(m,j+x,i+y))==1 || c==5) + if(map_getcell(m,j+x,i+y,CELL_CHKNOPASS)) continue; if(free_cell==0){ x+=j; @@ -797,7 +1301,7 @@ int map_searchrandfreecell(int m,int x,int y,int range) { } /*========================================== - * (m,x,y)‚ð’†S‚É3x3ˆÈ“à‚ɰƒAƒCƒeƒ€Ý’u + * (m,x,y)‚ð’†S‚É3x3ˆÈ?‚ɰƒAƒCƒeƒ€Ý’u * * item_data‚ÍamountˆÈŠO‚ðcopy‚·‚é *------------------------------------------ @@ -829,7 +1333,7 @@ int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,struct fitem->bl.id = map_addobject(&fitem->bl); if(fitem->bl.id==0){ - free(fitem); + aFree(fitem); return 0; } @@ -876,9 +1380,9 @@ void map_addchariddb(int charid, char *name) { struct charid2nick *p=NULL; int req=0; - p=numdb_search(charid_db,charid); - if(p==NULL){ // ƒf[ƒ^ƒx[ƒX‚ɂȂ¢ - p = (struct charid2nick *)aCalloc(1,sizeof(struct charid2nick)); + p = (struct charid2nick*)numdb_search(charid_db,charid); + if(p==NULL){ // ƒf?ƒ^ƒx?ƒX‚ɂȂ¢ + p = (struct charid2nick *)aCallocA(1,sizeof(struct charid2nick)); p->req_id=0; }else numdb_erase(charid_db,charid); @@ -903,8 +1407,8 @@ int map_reqchariddb(struct map_session_data * sd,int charid) { nullpo_retr(0, sd); - p=numdb_search(charid_db,charid); - if(p!=NULL) // ƒf[ƒ^ƒx[ƒX‚É‚·‚łɂ ‚é + p = (struct charid2nick*)numdb_search(charid_db,charid); + if(p!=NULL) // ƒf?ƒ^ƒx?ƒX‚É‚·‚łɂ ‚é return 0; p = (struct charid2nick *)aCalloc(1,sizeof(struct charid2nick)); p->req_id=sd->bl.id; @@ -943,105 +1447,133 @@ void map_addnickdb(struct map_session_data *sd) { } /*========================================== - * PC‚Ìquitˆ— map.c“à•ª + * PC‚Ìquit?— map.c?•ª * - * quitˆ—‚ÌŽå‘Ì‚ªˆá‚¤‚悤‚È‹C‚à‚µ‚Ä‚«‚½ + * quit?—‚ÌŽå?‚ªˆá‚¤‚悤‚È?‚à‚µ‚Ä‚«‚½ *------------------------------------------ */ int map_quit(struct map_session_data *sd) { - int i; - nullpo_retr(0, sd); - if(sd->chatID) // ƒ`ƒƒƒbƒg‚©‚ço‚é - chat_leavechat(sd); + if(!sd->state.waitingdisconnect) { + if (sd->state.event_disconnect) { + if (script_config.event_script_type == 0) { + struct npc_data *npc; + if ((npc = npc_name2id(script_config.logout_event_name))) { + run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLogoutNPC + sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.logout_event_name); + ShowStatus(tmp_output); + } + } else { + sprintf (tmp_output, "%d '"CL_WHITE"%s"CL_RESET"' events executed.\n", + npc_event_doall_id(script_config.logout_event_name, sd->bl.id), script_config.logout_event_name); + ShowStatus(tmp_output); + } + } - if(sd->trade_partner) // Žæˆø‚ð’†’f‚·‚é - trade_tradecancel(sd); + if(sd->chatID) // ƒ`ƒƒƒbƒg‚©‚ço‚é + chat_leavechat(sd); - if(sd->party_invite>0) // ƒp[ƒeƒBŠ©—U‚ð‹‘”Û‚·‚é - party_reply_invite(sd,sd->party_invite_account,0); + if(sd->trade_partner) // Žæˆø‚ð’†?‚·‚é + trade_tradecancel(sd); - if(sd->guild_invite>0) // ƒMƒ‹ƒhŠ©—U‚ð‹‘”Û‚·‚é - guild_reply_invite(sd,sd->guild_invite,0); - if(sd->guild_alliance>0) // ƒMƒ‹ƒh“¯–¿Š©—U‚ð‹‘”Û‚·‚é - guild_reply_reqalliance(sd,sd->guild_alliance_account,0); + if(sd->party_invite>0) // ƒp?ƒeƒB?—U‚ð‹‘”Û‚·‚é + party_reply_invite(sd,sd->party_invite_account,0); - party_send_logout(sd); // ƒp[ƒeƒB‚̃ƒOƒAƒEƒgƒƒbƒZ[ƒW‘—M + if(sd->guild_invite>0) // ƒMƒ‹ƒh?—U‚ð‹‘”Û‚·‚é + guild_reply_invite(sd,sd->guild_invite,0); + if(sd->guild_alliance>0) // ƒMƒ‹ƒh“¯–¿?—U‚ð‹‘”Û‚·‚é + guild_reply_reqalliance(sd,sd->guild_alliance_account,0); - guild_send_memberinfoshort(sd,0); // ƒMƒ‹ƒh‚̃ƒOƒAƒEƒgƒƒbƒZ[ƒW‘—M + party_send_logout(sd); // ƒp?ƒeƒB‚̃ƒOƒAƒEƒgƒƒbƒZ?ƒW‘—M - pc_cleareventtimer(sd); // ƒCƒxƒ“ƒgƒ^ƒCƒ}‚ð”jŠü‚·‚é + guild_send_memberinfoshort(sd,0); // ƒMƒ‹ƒh‚̃ƒOƒAƒEƒgƒƒbƒZ?ƒW‘—M - if(sd->state.storage_flag) - storage_guild_storage_quit(sd,0); - else - storage_storage_quit(sd); // ‘qŒÉ‚ðŠJ‚¢‚Ä‚é‚È‚ç•Û‘¶‚·‚é - - skill_castcancel(&sd->bl,0); // ‰r¥‚ð’†’f‚·‚é - skill_stop_dancing(&sd->bl,1);// ƒ_ƒ“ƒX/‰‰‘t’†’f - - if(sd->sc_data && sd->sc_data[SC_BERSERK].timer!=-1) //ƒo[ƒT[ƒN’†‚ÌI—¹‚ÍHP‚ð100‚É - sd->status.hp = 100; - - skill_status_change_clear(&sd->bl,1); // ƒXƒe[ƒ^ƒXˆÙí‚ð‰ðœ‚·‚é - skill_clear_unitgroup(&sd->bl); // ƒXƒLƒ‹ƒ†ƒjƒbƒgƒOƒ‹[ƒv‚Ìíœ - skill_cleartimerskill(&sd->bl); - pc_stop_walking(sd,0); - pc_stopattack(sd); - pc_delinvincibletimer(sd); - pc_delspiritball(sd,sd->spiritball,1); - skill_gangsterparadise(sd,0); - - pc_calcstatus(sd,4); - - clif_clearchar_area(&sd->bl,2); - - if(sd->status.pet_id && sd->pd) { - pet_lootitem_drop(sd->pd,sd); - pet_remove_map(sd); - if(sd->pet.intimate <= 0) { - intif_delete_petdata(sd->status.pet_id); - sd->status.pet_id = 0; - sd->pd = NULL; - sd->petDB = NULL; - } + pc_cleareventtimer(sd); // ƒCƒxƒ“ƒgƒ^ƒCƒ}‚ð”jŠü‚·‚é + + if(sd->state.storage_flag) + storage_guild_storage_quit(sd,0); else - intif_save_petdata(sd->status.account_id,&sd->pet); - } - - if(pc_isdead(sd)) - pc_setrestartvalue(sd,2); - pc_makesavestatus(sd); - //ƒNƒ[ƒ“ƒXƒLƒ‹‚ÅŠo‚¦‚½ƒXƒLƒ‹‚ÍÁ‚· - for(i=0;i<MAX_SKILL;i++){ - if(sd->status.skill[i].flag == 13){ - sd->status.skill[i].id=0; - sd->status.skill[i].lv=0; - sd->status.skill[i].flag=0; + storage_storage_quit(sd); // ‘qŒÉ‚ðŠJ‚¢‚Ä‚é‚È‚ç•Û‘¶‚·‚é + + // check if we've been authenticated [celest] + if (sd->state.auth) + skill_castcancel(&sd->bl,0); // ‰r¥‚ð’†?‚·‚é + + skill_stop_dancing(&sd->bl,1);// ƒ_ƒ“ƒX/‰‰‘t’†? + + if(sd->sc_data && sd->sc_data[SC_BERSERK].timer!=-1) //ƒo?ƒT?ƒN’†‚ÌI—¹‚ÍHP‚ð100‚É + sd->status.hp = 100; + + status_change_clear(&sd->bl,1); // ƒXƒe?ƒ^ƒXˆÙí‚ð‰ðœ‚·‚é + skill_clear_unitgroup(&sd->bl); // ƒXƒLƒ‹ƒ†ƒjƒbƒgƒOƒ‹?ƒv‚Ìíœ + skill_cleartimerskill(&sd->bl); + + // check if we've been authenticated [celest] + if (sd->state.auth) { + pc_stop_walking(sd,0); + pc_stopattack(sd); + pc_delinvincibletimer(sd); + } + pc_delspiritball(sd,sd->spiritball,1); + skill_gangsterparadise(sd,0); + skill_unit_move(&sd->bl,gettick(),0); + + if (sd->state.auth) + status_calc_pc(sd,4); + // skill_clear_unitgroup(&sd->bl); // [Sara-chan] + + clif_clearchar_area(&sd->bl,2); + + if(sd->status.pet_id && sd->pd) { + pet_lootitem_drop(sd->pd,sd); + pet_remove_map(sd); + if(sd->pet.intimate <= 0) { + intif_delete_petdata(sd->status.pet_id); + sd->status.pet_id = 0; + sd->pd = NULL; + sd->petDB = NULL; + } + else + intif_save_petdata(sd->status.account_id,&sd->pet); } - } - chrif_save(sd); - storage_storage_save(sd); - if( sd->npc_stackbuf && sd->npc_stackbuf != NULL) - free( sd->npc_stackbuf ); + if(pc_isdead(sd)) + pc_setrestartvalue(sd,2); - map_delblock(&sd->bl); + pc_clean_skilltree(sd); + pc_makesavestatus(sd); + chrif_save(sd); + storage_storage_dirty(sd); + storage_storage_save(sd); + map_delblock(&sd->bl); + } + + if( sd->npc_stackbuf && sd->npc_stackbuf != NULL) { + aFree( sd->npc_stackbuf ); + sd->npc_stackbuf = NULL; + } -#ifndef TXT_ONLY chrif_char_offline(sd); -#endif - numdb_erase(id_db,sd->bl.id); + { + void *p = numdb_search(charid_db,sd->status.char_id); + if(p) { + numdb_erase(charid_db,sd->status.char_id); + aFree(p); + } + } strdb_erase(nick_db,sd->status.name); numdb_erase(charid_db,sd->status.char_id); + numdb_erase(id_db,sd->bl.id); + aFree(sd->reg); + aFree(sd->regstr); return 0; } /*========================================== - * id”Ô†‚ÌPC‚ð’T‚·B‹‚È‚¯‚ê‚ÎNULL + * id”Ô?‚ÌPC‚ð’T‚·B‹‚È‚¯‚ê‚ÎNULL *------------------------------------------ */ struct map_session_data * map_id2sd(int id) { @@ -1060,21 +1592,23 @@ struct map_session_data * map_id2sd(int id) { return NULL; */ int i; - struct map_session_data *sd=NULL; + struct map_session_data *sd; + + if (id <= 0) return 0; for(i = 0; i < fd_max; i++) - if (session[i] && (sd = session[i]->session_data) && sd->bl.id == id) + if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd->bl.id == id) return sd; return NULL; } /*========================================== - * char_id”Ô†‚Ì–¼‘O‚ð’T‚· + * char_id”Ô?‚Ì–¼‘O‚ð’T‚· *------------------------------------------ */ char * map_charid2nick(int id) { - struct charid2nick *p=numdb_search(charid_db,id); + struct charid2nick *p = (struct charid2nick*)numdb_search(charid_db,id); if(p==NULL) return NULL; @@ -1083,6 +1617,18 @@ char * map_charid2nick(int id) { return p->nick; } +struct map_session_data * map_charid2sd(int id) { + int i; + struct map_session_data *sd; + + if (id <= 0) return 0; + + for(i = 0; i < fd_max; i++) + if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd->status.char_id == id) + return sd; + + return NULL; +} /*========================================== * Search session data from a nick name @@ -1101,7 +1647,7 @@ struct map_session_data * map_nick2sd(char *nick) { nicklen = strlen(nick); for (i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) + if (session[i] && (pl_sd = (struct map_session_data*)session[i]->session_data) && pl_sd->state.auth) // Without case sensitive check (increase the number of similar character names found) if (strnicmp(pl_sd->status.name, nick, nicklen) == 0) { // Strict comparison (if found, we finish the function immediatly with correct value) @@ -1121,27 +1667,27 @@ struct map_session_data * map_nick2sd(char *nick) { } /*========================================== - * id”Ô†‚Ì•¨‚ð’T‚· + * id”Ô?‚Ì•¨‚ð’T‚· * ˆêŽžobject‚Ìꇂ͔z—ñ‚ðˆø‚‚Ì‚Ý *------------------------------------------ */ struct block_list * map_id2bl(int id) { struct block_list *bl=NULL; - if(id<sizeof(object)/sizeof(object[0])) - bl = object[id]; + if(id >= 0 && id < sizeof(objects)/sizeof(objects[0])) + bl = objects[id]; else - bl = numdb_search(id_db,id); + bl = (struct block_list*)numdb_search(id_db,id); return bl; } /*========================================== - * id_db“à‚Ì‘S‚Ä‚Éfunc‚ðŽÀs + * id_db?‚Ì‘S‚Ä‚Éfunc‚ð?s *------------------------------------------ */ int map_foreachiddb(int (*func)(void*,void*,va_list),...) { - va_list ap=NULL; + va_list ap; va_start(ap,func); numdb_foreach(id_db,func,ap); @@ -1179,48 +1725,60 @@ int map_addnpc(int m,struct npc_data *nd) { } void map_removenpc(void) { - int i,m,n=0; - - for(m=0;m<map_num;m++) { - for(i=0;i<map[m].npc_num && i<MAX_NPC_PER_MAP;i++) { - if(map[m].npc[i]!=NULL) { - clif_clearchar_area(&map[m].npc[i]->bl,2); - map_delblock(&map[m].npc[i]->bl); - numdb_erase(id_db,map[m].npc[i]->bl.id); - if(map[m].npc[i]->bl.subtype==SCRIPT) { -// free(map[m].npc[i]->u.scr.script); -// free(map[m].npc[i]->u.scr.label_list); - } - free(map[m].npc[i]); - map[m].npc[i] = NULL; - n++; - } - } - } - printf("%d NPCs removed.\n",n); + int i,m,n=0; + + for(m=0;m<map_num;m++) { + for(i=0;i<map[m].npc_num && i<MAX_NPC_PER_MAP;i++) { + if(map[m].npc[i]!=NULL) { + clif_clearchar_area(&map[m].npc[i]->bl,2); + map_delblock(&map[m].npc[i]->bl); + numdb_erase(id_db,map[m].npc[i]->bl.id); + if(map[m].npc[i]->bl.subtype==SCRIPT) { + aFree(map[m].npc[i]->u.scr.script); + aFree(map[m].npc[i]->u.scr.label_list); + } + aFree(map[m].npc[i]); + map[m].npc[i] = NULL; + n++; + } + } + } + + sprintf(tmp_output,"Successfully removed and freed from memory '"CL_WHITE"%d"CL_RESET"' NPCs.\n",n); + ShowStatus(tmp_output); } /*========================================== - * map–¼‚©‚çmap”Ô†‚Ö•ÏŠ· + * map–¼‚©‚çmap”Ô?‚Ö?Š· *------------------------------------------ */ int map_mapname2mapid(char *name) { struct map_data *md=NULL; - md=strdb_search(map_db,name); + md = (struct map_data*)strdb_search(map_db,name); + +#ifdef USE_AFM + // If we can't find the .gat map try .afm instead [celest] + if(md==NULL && strstr(name,".gat")) { + char *afm_name = strdup(name); + strcpy(&afm_name[strlen(name) - 3], "afm"); + md = (struct map_data*)strdb_search(map_db,afm_name); + } +#endif + if(md==NULL || md->gat==NULL) return -1; return md->m; } /*========================================== - * ‘¼ŽImap–¼‚©‚çip,port•ÏŠ· + * ‘¼ŽImap–¼‚©‚çip,port?Š· *------------------------------------------ */ int map_mapname2ipport(char *name,int *ip,int *port) { struct map_data_other_server *mdos=NULL; - mdos=strdb_search(map_db,name); + mdos = (struct map_data_other_server*)strdb_search(map_db,name); if(mdos==NULL || mdos->gat) return -1; *ip=mdos->ip; @@ -1311,20 +1869,74 @@ int map_calc_dir( struct block_list *src,int x,int y) { * (m,x,y)‚Ìó‘Ԃ𒲂ׂé *------------------------------------------ */ -int map_getcell(int m,int x,int y) { - if(x<0 || x>=map[m].xs-1 || y<0 || y>=map[m].ys-1) - return 1; - return map[m].gat[x+y*map[m].xs]; + +int map_getcell(int m,int x,int y,cell_t cellchk) +{ + return (m < 0 || m > MAX_MAP_PER_SERVER) ? 0 : map_getcellp(&map[m],x,y,cellchk); +} + +int map_getcellp(struct map_data* m,int x,int y,cell_t cellchk) +{ + int type; + nullpo_ret(m); + + if(x<0 || x>=m->xs-1 || y<0 || y>=m->ys-1) + { + if(cellchk==CELL_CHKNOPASS) return 1; + return 0; + } + type = m->gat[x+y*m->xs]; + if (cellchk<0x10) + type &= CELL_MASK; + + switch(cellchk) + { + case CELL_CHKPASS: + return (type!=1 && type!=5); + case CELL_CHKNOPASS: + return (type==1 || type==5); + case CELL_CHKWALL: + return (type==1); + case CELL_CHKWATER: + return (type==3); + case CELL_CHKGROUND: + return (type==5); + case CELL_GETTYPE: + return type; + case CELL_CHKNPC: + return (type&CELL_NPC); + case CELL_CHKBASILICA: + return (type&CELL_BASILICA); + default: + return 0; + } } /*========================================== - * (m,x,y)‚Ìó‘Ô‚ðt‚É‚·‚é + * (m,x,y)‚Ìó‘Ô‚ðÝ’è‚·‚é *------------------------------------------ */ -int map_setcell(int m,int x,int y,int t) { +void map_setcell(int m,int x,int y,int cell) +{ + int j; if(x<0 || x>=map[m].xs || y<0 || y>=map[m].ys) - return t; - return map[m].gat[x+y*map[m].xs]=t; + return; + j=x+y*map[m].xs; + + switch (cell) { + case CELL_SETNPC: + map[m].gat[j] |= CELL_NPC; + break; + case CELL_SETBASILICA: + map[m].gat[j] |= CELL_BASILICA; + break; + case CELL_CLRBASILICA: + map[m].gat[j] &= ~CELL_BASILICA; + break; + default: + map[m].gat[j] = (map[m].gat[j]&~CELL_MASK) + cell; + break; + } } /*========================================== @@ -1335,22 +1947,46 @@ int map_setipport(char *name,unsigned long ip,int port) { struct map_data *md=NULL; struct map_data_other_server *mdos=NULL; - md=strdb_search(map_db,name); + md = (struct map_data*)strdb_search(map_db,name); if(md==NULL){ // not exist -> add new data mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server)); memcpy(mdos->name,name,24); mdos->gat = NULL; mdos->ip = ip; mdos->port = port; + mdos->map = NULL; strdb_insert(map_db,mdos->name,mdos); + } else if(md->gat){ + if(ip!=clif_getip() || port!=clif_getport()){ + // “ǂݞ‚ñ‚Å‚¢‚½‚¯‚ÇA’S“–ŠO‚ɂȂÁ‚½ƒ}ƒbƒv + mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server)); + memcpy(mdos->name,name,24); + mdos->gat = NULL; + mdos->ip = ip; + mdos->port = port; + mdos->map = md; + strdb_insert(map_db,mdos->name,mdos); + // printf("from char server : %s -> %08lx:%d\n",name,ip,port); + } else { + // “ǂݞ‚ñ‚Å‚¢‚ÄA’S“–‚ɂȂÁ‚½ƒ}ƒbƒvi‰½‚à‚µ‚È‚¢j + ; + } } else { - if(md->gat){ // local -> check data - if(ip!=clif_getip() || port!=clif_getport()){ - printf("from char server : %s -> %08lx:%d\n",name,ip,port); - return 1; + mdos=(struct map_data_other_server *)md; + if(ip == clif_getip() && port == clif_getport()) { + // Ž©•ª‚Ì’S“–‚ɂȂÁ‚½ƒ}ƒbƒv + if(mdos->map == NULL) { + // “ǂݞ‚ñ‚Å‚¢‚È‚¢‚Ì‚ÅI—¹‚·‚é + printf("map_setipport : %s is not loaded.\n",name); + exit(1); + } else { + // “ǂݞ‚ñ‚Å‚¢‚é‚̂Œu‚«Š·‚¦‚é + md = mdos->map; + aFree(mdos); + strdb_insert(map_db,md->name,md); } - } else { // update - mdos=(struct map_data_other_server *)md; + } else { + // ‘¼‚ÌŽI‚Ì’S“–ƒ}ƒbƒv‚Ȃ̂Œu‚«Š·‚¦‚邾‚¯ mdos->ip = ip; mdos->port = port; } @@ -1358,12 +1994,62 @@ int map_setipport(char *name,unsigned long ip,int port) { return 0; } +/*========================================== + * ‘¼ŽIŠÇ—‚̃}ƒbƒv‚ð‘S‚Äíœ + *------------------------------------------ + */ +int map_eraseallipport_sub(void *key,void *data,va_list va) { + struct map_data_other_server *mdos = (struct map_data_other_server*)data; + if(mdos->gat == NULL && mdos->map == NULL) { + strdb_erase(map_db,key); + aFree(mdos); + } + return 0; +} + +int map_eraseallipport(void) { + strdb_foreach(map_db,map_eraseallipport_sub); + return 1; +} + +/*========================================== + * ‘¼ŽIŠÇ—‚̃}ƒbƒv‚ðdb‚©‚çíœ + *------------------------------------------ + */ +int map_eraseipport(char *name,unsigned long ip,int port) +{ + struct map_data *md; + struct map_data_other_server *mdos; +// unsigned char *p=(unsigned char *)&ip; + + md=(struct map_data *) strdb_search(map_db,name); + if(md){ + if(md->gat) // local -> check data + return 0; + else { + mdos=(struct map_data_other_server *)md; + if(mdos->ip==ip && mdos->port == port) { + if(mdos->map) { + // ‚±‚̃}ƒbƒvŽI‚Å‚à“ǂݞ‚ñ‚Å‚¢‚é‚̂ňړ®‚Å‚«‚é + return 1; // ŒÄ‚Ño‚µŒ³‚Å chrif_sendmap() ‚ð‚·‚é + } else { + strdb_erase(map_db,name); + aFree(mdos); + } +// if(battle_config.etc_log) +// printf("erase map %s %d.%d.%d.%d:%d\n",name,p[0],p[1],p[2],p[3],port); + } + } + } + return 0; +} + // ‰Šú‰»Žü‚è /*========================================== * …ê‚‚³Ý’è *------------------------------------------ */ -static struct { +static struct waterlist_ { char mapname[24]; int waterheight; } *waterlist=NULL; @@ -1391,7 +2077,7 @@ static void map_readwater(char *watertxt) { return; } if(waterlist==NULL) - waterlist=aCalloc(MAX_MAP_PER_SERVER,sizeof(*waterlist)); + waterlist = (struct waterlist_*)aCallocA(MAX_MAP_PER_SERVER,sizeof(*waterlist)); while(fgets(line,1020,fp) && n < MAX_MAP_PER_SERVER){ int wh,count; if(line[0] == '/' && line[1] == '/') @@ -1408,8 +2094,244 @@ static void map_readwater(char *watertxt) { } fclose(fp); } +/*========================================== +* ƒ}ƒbƒvƒLƒƒƒbƒVƒ…‚ɒljÁ‚·‚é +*===========================================*/ + +// ƒ}ƒbƒvƒLƒƒƒbƒVƒ…‚ÌÅ‘å’l +#define MAX_MAP_CACHE 768 + +//Šeƒ}ƒbƒv‚²‚Æ‚ÌŬŒÀî•ñ‚ð“ü‚ê‚é‚à‚ÌAREAD_FROM_BITMAP—p +struct map_cache_info { + char fn[32];//ƒtƒ@ƒCƒ‹–¼ + int xs,ys; //•‚Æ‚‚³ + int water_height; + int pos; // ƒf[ƒ^‚ª“ü‚ê‚Ä‚ ‚éêŠ + int compressed; // zilb’Ê‚¹‚邿‚¤‚É‚·‚éˆ×‚Ì—\–ñ + int compressed_len; // zilb’Ê‚¹‚邿‚¤‚É‚·‚éˆ×‚Ì—\–ñ +}; // 56 byte + +struct map_cache_head { + int sizeof_header; + int sizeof_map; + // ã‚Ì‚Q‚‰ü•Ï•s‰Â + int nmaps; // ƒ}ƒbƒv‚̌” + int filesize; +}; + +struct { + struct map_cache_head head; + struct map_cache_info *map; + FILE *fp; + int dirty; +} map_cache; + +static int map_cache_open(char *fn); +static void map_cache_close(void); +static int map_cache_read(struct map_data *m); +static int map_cache_write(struct map_data *m); + +static int map_cache_open(char *fn) +{ + atexit(map_cache_close); + if(map_cache.fp) { + map_cache_close(); + } + map_cache.fp = fopen(fn,"r+b"); + if(map_cache.fp) { + fread(&map_cache.head,1,sizeof(struct map_cache_head),map_cache.fp); + fseek(map_cache.fp,0,SEEK_END); + if( + map_cache.head.sizeof_header == sizeof(struct map_cache_head) && + map_cache.head.sizeof_map == sizeof(struct map_cache_info) && + map_cache.head.nmaps == MAX_MAP_CACHE && + map_cache.head.filesize == ftell(map_cache.fp) + ) { + // ƒLƒƒƒbƒVƒ…“ǂݞ‚ݬŒ÷ + map_cache.map = (struct map_cache_info *) aMalloc(sizeof(struct map_cache_info) * map_cache.head.nmaps); + fseek(map_cache.fp,sizeof(struct map_cache_head),SEEK_SET); + fread(map_cache.map,sizeof(struct map_cache_info),map_cache.head.nmaps,map_cache.fp); + return 1; + } + fclose(map_cache.fp); + } + // “ǂݞ‚݂Ɏ¸”s‚µ‚½‚Ì‚ÅV‹K‚É쬂·‚é + map_cache.fp = fopen(fn,"wb"); + if(map_cache.fp) { + memset(&map_cache.head,0,sizeof(struct map_cache_head)); + map_cache.map = (struct map_cache_info *) aCalloc(sizeof(struct map_cache_info),MAX_MAP_CACHE); + map_cache.head.nmaps = MAX_MAP_CACHE; + map_cache.head.sizeof_header = sizeof(struct map_cache_head); + map_cache.head.sizeof_map = sizeof(struct map_cache_info); + + map_cache.head.filesize = sizeof(struct map_cache_head); + map_cache.head.filesize += sizeof(struct map_cache_info) * map_cache.head.nmaps; + + map_cache.dirty = 1; + return 1; + } + return 0; +} + +static void map_cache_close(void) +{ + if(!map_cache.fp) { return; } + if(map_cache.dirty) { + fseek(map_cache.fp,0,SEEK_SET); + fwrite(&map_cache.head,1,sizeof(struct map_cache_head),map_cache.fp); + fwrite(map_cache.map,map_cache.head.nmaps,sizeof(struct map_cache_info),map_cache.fp); + } + fclose(map_cache.fp); + aFree(map_cache.map); + map_cache.fp = NULL; + return; +} + +int map_cache_read(struct map_data *m) +{ + int i; + if(!map_cache.fp) { return 0; } + for(i = 0;i < map_cache.head.nmaps ; i++) { + if(!strcmp(m->name,map_cache.map[i].fn)) { + if(map_cache.map[i].water_height != map_waterheight(m->name)) { + // …ê‚Ì‚‚³‚ªˆá‚¤‚̂œǂݒ¼‚µ + return 0; + } else if(map_cache.map[i].compressed == 0) { + // ”ñˆ³kƒtƒ@ƒCƒ‹ + int size = map_cache.map[i].xs * map_cache.map[i].ys; + m->xs = map_cache.map[i].xs; + m->ys = map_cache.map[i].ys; + m->gat = (unsigned char *)aCalloc(m->xs * m->ys,sizeof(unsigned char)); + fseek(map_cache.fp,map_cache.map[i].pos,SEEK_SET); + if(fread(m->gat,1,size,map_cache.fp) == size) { + // ¬Œ÷ + return 1; + } else { + // ‚È‚º‚©ƒtƒ@ƒCƒ‹Œã”¼‚ªŒ‡‚¯‚Ä‚é‚̂œǂݒ¼‚µ + m->xs = 0; m->ys = 0; m->gat = NULL; aFree(m->gat); + return 0; + } + } else if(map_cache.map[i].compressed == 1) { + // ˆ³kƒtƒ‰ƒO=1 : zlib + unsigned char *buf; + unsigned long dest_len; + int size_compress = map_cache.map[i].compressed_len; + m->xs = map_cache.map[i].xs; + m->ys = map_cache.map[i].ys; + m->gat = (unsigned char *)aMalloc(m->xs * m->ys * sizeof(unsigned char)); + buf = (unsigned char*)aMalloc(size_compress); + fseek(map_cache.fp,map_cache.map[i].pos,SEEK_SET); + if(fread(buf,1,size_compress,map_cache.fp) != size_compress) { + // ‚È‚º‚©ƒtƒ@ƒCƒ‹Œã”¼‚ªŒ‡‚¯‚Ä‚é‚̂œǂݒ¼‚µ + printf("fread error\n"); + aFree(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL; + aFree(buf); + return 0; + } + dest_len = m->xs * m->ys; + decode_zip(m->gat,&dest_len,buf,size_compress); + if(dest_len != map_cache.map[i].xs * map_cache.map[i].ys) { + // ³í‚ɉ𓀂ªo—ˆ‚ĂȂ¢ + aFree(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL; + aFree(buf); + return 0; + } + aFree(buf); + return 1; + } + } + } + return 0; +} +static int map_cache_write(struct map_data *m) +{ + int i; + unsigned long len_new , len_old; + char *write_buf; + if(!map_cache.fp) { return 0; } + for(i = 0;i < map_cache.head.nmaps ; i++) { + if(!strcmp(m->name,map_cache.map[i].fn)) { + // “¯‚¶ƒGƒ“ƒgƒŠ[‚ª‚ ‚ê‚Îã‘‚« + if(map_cache.map[i].compressed == 0) { + len_old = map_cache.map[i].xs * map_cache.map[i].ys; + } else if(map_cache.map[i].compressed == 1) { + len_old = map_cache.map[i].compressed_len; + } else { + // ƒTƒ|[ƒg‚³‚ê‚ĂȂ¢Œ`Ž®‚Ȃ̂Œ·‚³‚O + len_old = 0; + } + if(map_read_flag == 2) { + // ˆ³k•Û‘¶ + // ‚³‚·‚ª‚É‚Q”{‚É–c‚ê‚鎖‚͂Ȃ¢‚Æ‚¢‚¤Ž–‚Å + write_buf = (char *) aMalloc(m->xs * m->ys * 2); + len_new = m->xs * m->ys * 2; + encode_zip((unsigned char *) write_buf,&len_new,m->gat,m->xs * m->ys); + map_cache.map[i].compressed = 1; + map_cache.map[i].compressed_len = len_new; + } else { + len_new = m->xs * m->ys; + write_buf = (char *) m->gat; + map_cache.map[i].compressed = 0; + map_cache.map[i].compressed_len = 0; + } + if(len_new <= len_old) { + // ƒTƒCƒY‚ª“¯‚¶‚©¬‚³‚‚È‚Á‚½‚Ì‚Åꊂ͕ςí‚ç‚È‚¢ + fseek(map_cache.fp,map_cache.map[i].pos,SEEK_SET); + fwrite(write_buf,1,len_new,map_cache.fp); + } else { + // V‚µ‚¢êЂɓo˜^ + fseek(map_cache.fp,map_cache.head.filesize,SEEK_SET); + fwrite(write_buf,1,len_new,map_cache.fp); + map_cache.map[i].pos = map_cache.head.filesize; + map_cache.head.filesize += len_new; + } + map_cache.map[i].xs = m->xs; + map_cache.map[i].ys = m->ys; + map_cache.map[i].water_height = map_waterheight(m->name); + map_cache.dirty = 1; + if(map_read_flag == 2) { + aFree(write_buf); + } + return 0; + } + } + // “¯‚¶ƒGƒ“ƒgƒŠ‚ª–³‚¯‚ê‚Α‚«ž‚ß‚éꊂð’T‚· + for(i = 0;i < map_cache.head.nmaps ; i++) { + if(map_cache.map[i].fn[0] == 0) { + // V‚µ‚¢êЂɓo˜^ + if(map_read_flag == 2) { + write_buf = (char *) aMalloc(m->xs * m->ys * 2); + len_new = m->xs * m->ys * 2; + encode_zip((unsigned char *) write_buf,&len_new,m->gat,m->xs * m->ys); + map_cache.map[i].compressed = 1; + map_cache.map[i].compressed_len = len_new; + } else { + len_new = m->xs * m->ys; + write_buf = (char *) m->gat; + map_cache.map[i].compressed = 0; + map_cache.map[i].compressed_len = 0; + } + strncpy(map_cache.map[i].fn,m->name,sizeof(map_cache.map[0].fn)); + fseek(map_cache.fp,map_cache.head.filesize,SEEK_SET); + fwrite(write_buf,1,len_new,map_cache.fp); + map_cache.map[i].pos = map_cache.head.filesize; + map_cache.map[i].xs = m->xs; + map_cache.map[i].ys = m->ys; + map_cache.map[i].water_height = map_waterheight(m->name); + map_cache.head.filesize += len_new; + map_cache.dirty = 1; + if(map_read_flag == 2) { + aFree(write_buf); + } + return 0; + } + } + // ‘‚«ž‚߂Ȃ©‚Á‚½ + return 1; +} +#ifdef USE_AFM static int map_readafm(int m,char *fn) { /* @@ -1474,7 +2396,7 @@ static int map_readafm(int m,char *fn) { size_t size; char afm_line[65535]; - int afm_size[1]; + int afm_size[2]; FILE *afm_file; char *str; @@ -1492,7 +2414,8 @@ static int map_readafm(int m,char *fn) { map[m].m = m; xs = map[m].xs = afm_size[0]; ys = map[m].ys = afm_size[1]; - map[m].gat = calloc(s = map[m].xs * map[m].ys, 1); + // check this, unsigned where it might not need to be + map[m].gat = (unsigned char*)aCallocA(s = map[m].xs * map[m].ys, 1); if(map[m].gat==NULL){ printf("out of memory : map_readmap gat\n"); @@ -1515,14 +2438,14 @@ static int map_readafm(int m,char *fn) { map[m].bxs=(xs+BLOCK_SIZE-1)/BLOCK_SIZE; map[m].bys=(ys+BLOCK_SIZE-1)/BLOCK_SIZE; size = map[m].bxs * map[m].bys * sizeof(struct block_list*); - map[m].block = calloc(size, 1); + map[m].block = (struct block_list**)aCalloc(size, 1); if(map[m].block == NULL){ printf("out of memory : map_readmap block\n"); exit(1); } - map[m].block_mob = calloc(size, 1); + map[m].block_mob = (struct block_list**)aCalloc(size, 1); if (map[m].block_mob == NULL) { printf("out of memory : map_readmap block_mob\n"); exit(1); @@ -1530,14 +2453,14 @@ static int map_readafm(int m,char *fn) { size = map[m].bxs*map[m].bys*sizeof(int); - map[m].block_count = calloc(size, 1); + map[m].block_count = (int*)aCallocA(size, 1); if(map[m].block_count==NULL){ printf("out of memory : map_readmap block\n"); exit(1); } memset(map[m].block_count,0,size); - map[m].block_mob_count=calloc(size, 1); + map[m].block_mob_count = (int*)aCallocA(size, 1); if(map[m].block_mob_count==NULL){ printf("out of memory : map_readmap block_mob\n"); exit(1); @@ -1552,58 +2475,100 @@ static int map_readafm(int m,char *fn) { return 0; } +#endif /*========================================== * ƒ}ƒbƒv1–‡“ǂݞ‚Ý - *------------------------------------------ - */ -static int map_readmap(int m,char *fn, char *alias) { - unsigned char *gat=""; - int s; - int x,y,xs,ys; - struct gat_1cell {float high[4]; int type;} *p=NULL; - int wh; + * ===================================================*/ +static int map_readmap(int m,char *fn, char *alias, int *map_cache, int maxmap) { + char *gat=""; size_t size; - // read & convert fn - gat=grfio_read(fn); - if(gat==NULL) - return -1; + int i = 0; + int e = 0; + char progress[21] = " "; + + //printf("\rLoading Maps [%d/%d]: %-50s ",m,map_num,fn); + if (maxmap) { //avoid map-server crashing if there are 0 maps + char c = '-'; + static int lasti = -1; + static int last_time = -1; + i=m*20/maxmap; + if ((i != lasti) || (last_time != time(0))) { + lasti = i; + printf("\r"); + ShowStatus("Progress: "); + printf("["); + for (e=0;e<i;e++) progress[e] = '#'; + printf(progress); + printf("] Working: ["); + last_time = time(0); + switch(last_time % 4) { + case 0: c='\\'; break; + case 1: c='|'; break; + case 2: c='/'; break; + case 3: c='-'; break; + } + printf("%c]",c); + fflush(stdout); + } + } -// printf("\rLoading Maps [%d/%d]: %-50s ",m,map_num,fn); -// fflush(stdout); + if(map_cache_read(&map[m])) { + // ƒLƒƒƒbƒVƒ…‚©‚ç“ǂݞ‚ß‚½ + (*map_cache)++; + } else { + int s; + int wh; + int x,y,xs,ys; + struct gat_1cell {float high[4]; int type;} *p=NULL; + // read & convert fn + // again, might not need to be unsigned char + gat = (char*)grfio_read(fn); + if(gat==NULL) { + return -1; + // ‚³‚·‚ª‚Ƀ}ƒbƒv‚ª“ǂ߂Ȃ¢‚̂͂܂¸‚¢‚Ì‚ÅI—¹‚·‚é + //printf("Can't load map %s\n",fn); + //exit(1); + } - map[m].m=m; - xs=map[m].xs=*(int*)(gat+6); - ys=map[m].ys=*(int*)(gat+10); - map[m].gat = (unsigned char *)aCalloc(s = map[m].xs * map[m].ys,sizeof(unsigned char)); - map[m].npc_num=0; - map[m].users=0; - memset(&map[m].flag,0,sizeof(map[m].flag)); - if(battle_config.pk_mode) map[m].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris] - wh=map_waterheight(map[m].name); - for(y=0;y<ys;y++){ - p=(struct gat_1cell*)(gat+y*xs*20+14); - for(x=0;x<xs;x++){ - if(wh!=NO_WATER && p->type==0){ - // …ê”»’è - map[m].gat[x+y*xs]=(p->high[0]>wh || p->high[1]>wh || p->high[2]>wh || p->high[3]>wh) ? 3 : 0; - } else { - map[m].gat[x+y*xs]=p->type; + xs=map[m].xs=*(int*)(gat+6); + ys=map[m].ys=*(int*)(gat+10); + map[m].gat = (unsigned char *)aCallocA(s = map[m].xs * map[m].ys,sizeof(unsigned char)); + wh=map_waterheight(map[m].name); + for(y=0;y<ys;y++){ + p=(struct gat_1cell*)(gat+y*xs*20+14); + for(x=0;x<xs;x++){ + if(wh!=NO_WATER && p->type==0){ + // …ê”»’è + map[m].gat[x+y*xs]=(p->high[0]>wh || p->high[1]>wh || p->high[2]>wh || p->high[3]>wh) ? 3 : 0; + } else { + map[m].gat[x+y*xs]=p->type; + } + p++; } - p++; } + map_cache_write(&map[m]); + aFree(gat); } - free(gat); - map[m].bxs=(xs+BLOCK_SIZE-1)/BLOCK_SIZE; - map[m].bys=(ys+BLOCK_SIZE-1)/BLOCK_SIZE; + map[m].m=m; + map[m].npc_num=0; + map[m].users=0; + memset(&map[m].flag,0,sizeof(map[m].flag)); + if(battle_config.pk_mode) + map[m].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris] + map[m].bxs=(map[m].xs+BLOCK_SIZE-1)/BLOCK_SIZE; + map[m].bys=(map[m].ys+BLOCK_SIZE-1)/BLOCK_SIZE; size = map[m].bxs * map[m].bys * sizeof(struct block_list*); map[m].block = (struct block_list **)aCalloc(1,size); map[m].block_mob = (struct block_list **)aCalloc(1,size); size = map[m].bxs*map[m].bys*sizeof(int); - map[m].block_count = (int *)aCalloc(1,size); - map[m].block_mob_count=(int *)aCalloc(1,size); + map[m].block_count = (int *)aCallocA(1,size); + map[m].block_mob_count=(int *)aCallocA(1,size); + if (alias) + strdb_insert(map_db,alias,&map[m]); + else strdb_insert(map_db,map[m].name,&map[m]); // printf("%s read done\n",fn); @@ -1612,57 +2577,90 @@ static int map_readmap(int m,char *fn, char *alias) { } /*========================================== - * ‘S‚Ä‚Ìmapƒf[ƒ^‚ð“ǂݞ‚Þ + * ‘S‚Ä‚Ìmapƒf?ƒ^‚ð?‚Ý?‚Þ *------------------------------------------ */ int map_readallmap(void) { int i,maps_removed=0; char fn[256]; +#ifdef USE_AFM FILE *afm_file; +#endif + int map_cache = 0; + + // ƒ}ƒbƒvƒLƒƒƒbƒVƒ…‚ðŠJ‚ + if(map_read_flag >= READ_FROM_BITMAP) { + map_cache_open(map_cache_file); + } + + sprintf(tmp_output, "Loading Maps%s...\n", + (map_read_flag == CREATE_BITMAP_COMPRESSED ? " (Generating Map Cache w/ Compression)" : + map_read_flag == CREATE_BITMAP ? " (Generating Map Cache)" : + map_read_flag >= READ_FROM_BITMAP ? " (w/ Map Cache)" : + map_read_flag == READ_FROM_AFM ? " (w/ AFM)" : "")); + ShowStatus(tmp_output); // æ‚É‘S•”‚̃ƒbƒv‚Ì‘¶Ý‚ðŠm”F for(i=0;i<map_num;i++){ - char afm_name[256] = ""; - strncpy(afm_name, map[i].name, strlen(map[i].name) - 4); - strcat(afm_name, ".afm"); +#ifdef USE_AFM + char afm_name[256] = ""; + char *p; + if(!strstr(map[i].name,".afm")) { + // check if it's necessary to replace the extension - speeds up loading abit + strncpy(afm_name, map[i].name, strlen(map[i].name) - 4); + strcat(afm_name, ".afm"); + } + map[i].alias = NULL; sprintf(fn,"%s\\%s",afm_dir,afm_name); + for(p=&fn[0];*p!=0;p++) if (*p=='\\') *p = '/'; // * At the time of Unix + afm_file = fopen(fn, "r"); if (afm_file != NULL) { map_readafm(i,fn); fclose(afm_file); } else if(strstr(map[i].name,".gat")!=NULL) { - char *p = strstr(map[i].name, ">"); // [MouseJstr] +#else + if(strstr(map[i].name,".gat")!=NULL) { +#endif + char *p = strstr(map[i].name, "<"); // [MouseJstr] if (p != NULL) { - char alias[64]; - *p = '\0'; - strcpy(alias, map[i].name); - strcpy(map[i].name, p + 1); - sprintf(fn,"data\\%s",map[i].name); - if(map_readmap(i,fn, alias) == -1) { - map_delmap(map[i].name); - maps_removed++; - } - } else { - sprintf(fn,"data\\%s",map[i].name); - if(map_readmap(i,fn, NULL) == -1) { - map_delmap(map[i].name); - maps_removed++; - } + char buf[64]; + *p++ = '\0'; + sprintf(buf,"data\\%s", p); + map[i].alias = aStrdup(buf); + } else + map[i].alias = NULL; + + sprintf(fn,"data\\%s",map[i].name); + if(map_readmap(i,fn, p, &map_cache, map_num) == -1) { + map_delmap(map[i].name); + maps_removed++; + i--; } } } - free(waterlist); - printf("\rMaps Loaded: %d %60s\n",map_num,""); - printf("\rMaps Removed: %d \n",maps_removed); + aFree(waterlist); + printf("\r"); + snprintf(tmp_output,sizeof(tmp_output),"Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps.%30s\n",map_num,""); + ShowInfo(tmp_output); + + map_cache_close(); + if(map_read_flag == CREATE_BITMAP || map_read_flag == CREATE_BITMAP_COMPRESSED) { + --map_read_flag; + } + if (maps_removed) { + snprintf(tmp_output,sizeof(tmp_output),"Maps Removed: '"CL_WHITE"%d"CL_RESET"'\n",maps_removed); + ShowNotice(tmp_output); + } return 0; } /*========================================== - * “ǂݞ‚Þmap‚ð’ljÁ‚·‚é + * ?‚Ý?‚Þmap‚ð’ljÁ‚·‚é *------------------------------------------ */ int map_addmap(char *mapname) { @@ -1672,7 +2670,9 @@ int map_addmap(char *mapname) { } if (map_num >= MAX_MAP_PER_SERVER - 1) { - printf("too many map\n"); + snprintf(tmp_output,sizeof(tmp_output),"Could not add map '" + CL_WHITE"%s"CL_RESET"', the limit of maps has been reached.\n",mapname); + ShowError(tmp_output); return 1; } memcpy(map[map_num].name, mapname, 24); @@ -1681,7 +2681,7 @@ int map_addmap(char *mapname) { } /*========================================== - * “ǂݞ‚Þmap‚ð휂·‚é + * ?‚Ý?‚Þmap‚ð휂·‚é *------------------------------------------ */ int map_delmap(char *mapname) { @@ -1705,6 +2705,7 @@ int map_delmap(char *mapname) { static int map_ip_set_ = 0; static int char_ip_set_ = 0; +//static int bind_ip_set_ = 0; /*========================================== * Console Command Parser [Wizputer] @@ -1716,15 +2717,15 @@ int parse_console(char *buf) { int m, n; struct map_session_data *sd; - sd = calloc(sizeof(*sd), 1); + sd = (struct map_session_data*)aCalloc(sizeof(*sd), 1); sd->fd = 0; strcpy( sd->status.name , "console"); - type = (char *)malloc(64); - command = (char *)malloc(64); - map = (char *)malloc(64); - buf2 = (char *)malloc(72); + type = (char *)aMallocA(64); + command = (char *)aMallocA(64); + map = (char *)aMallocA(64); + buf2 = (char *)aMallocA(72); memset(type,0,64); memset(command,0,64); @@ -1781,18 +2782,18 @@ int parse_console(char *buf) { } end: - free(buf); - free(type); - free(command); - free(map); - free(buf2); - free(sd); + aFree(buf); + aFree(type); + aFree(command); + aFree(map); + aFree(buf2); + aFree(sd); return 0; } /*========================================== - * Ý’èƒtƒ@ƒCƒ‹‚ð“ǂݞ‚Þ + * Ý’èƒtƒ@ƒCƒ‹‚ð?‚Ý?‚Þ *------------------------------------------ */ int map_config_read(char *cfgName) { @@ -1817,7 +2818,7 @@ int map_config_read(char *cfgName) { char_ip_set_ = 1; h = gethostbyname (w2); if(h != NULL) { - snprintf(tmp_output,sizeof(tmp_output),"Character server IP address : %s -> %d.%d.%d.%d\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + snprintf(tmp_output,sizeof(tmp_output),"Char Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); ShowInfo(tmp_output); sprintf(w2,"%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); } @@ -1828,10 +2829,20 @@ int map_config_read(char *cfgName) { map_ip_set_ = 1; h = gethostbyname (w2); if (h != NULL) { - printf("Map server IP address : %s -> %d.%d.%d.%d\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + snprintf(tmp_output,sizeof(tmp_output),"Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + ShowInfo(tmp_output); sprintf(w2, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); } clif_setip(w2); + } else if (strcmpi(w1, "bind_ip") == 0) { + //bind_ip_set_ = 1; + h = gethostbyname (w2); + if (h != NULL) { + snprintf(tmp_output,sizeof(tmp_output),"Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + ShowInfo(tmp_output); + sprintf(w2, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]); + } + clif_setbindip(w2); } else if (strcmpi(w1, "map_port") == 0) { clif_setport(atoi(w2)); map_port = (atoi(w2)); @@ -1861,11 +2872,22 @@ int map_config_read(char *cfgName) { strcpy(help_txt, w2); } else if (strcmpi(w1, "mapreg_txt") == 0) { strcpy(mapreg_txt, w2); + }else if(strcmpi(w1,"read_map_from_cache")==0){ + if (atoi(w2) == 2) + map_read_flag = READ_FROM_BITMAP_COMPRESSED; + else if (atoi(w2) == 1) + map_read_flag = READ_FROM_BITMAP; + else + map_read_flag = READ_FROM_GAT; + }else if(strcmpi(w1,"map_cache_file")==0){ + strncpy(map_cache_file,w2,255); } else if (strcmpi(w1, "import") == 0) { map_config_read(w2); } else if (strcmpi(w1, "console") == 0) { - if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 ) + if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 ) { console = 1; + ShowNotice("Console Commands is enabled.\n"); + } } else if(strcmpi(w1,"imalive_on")==0){ //Added by Mugendai for I'm Alive mod imalive_on = atoi(w2); //Added by Mugendai for I'm Alive mod } else if(strcmpi(w1,"imalive_time")==0){ //Added by Mugendai for I'm Alive mod @@ -1883,82 +2905,7 @@ int map_config_read(char *cfgName) { return 0; } -#ifndef TXT_ONLY -/*======================================= - * MySQL Init - *--------------------------------------- - */ - -int map_sql_init(void){ - - mysql_init(&mmysql_handle); - - //DB connection start - printf("Connect Map DB Server....\n"); - if(!mysql_real_connect(&mmysql_handle, map_server_ip, map_server_id, map_server_pw, - map_server_db ,map_server_port, (char *)NULL, 0)) { - //pointer check - printf("%s\n",mysql_error(&mmysql_handle)); - exit(1); - } - else { - printf ("connect success! (Map Server Connection)\n"); - } - - mysql_init(&lmysql_handle); - - //DB connection start - printf("Connect Login DB Server....\n"); - if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw, - login_server_db ,login_server_port, (char *)NULL, 0)) { - //pointer check - printf("%s\n",mysql_error(&lmysql_handle)); - exit(1); - } - else { - printf ("connect success! (Login Server Connection)\n"); - } - - if(battle_config.mail_system) { // mail system [Valaris] - mysql_init(&mail_handle); - if(!mysql_real_connect(&mail_handle, map_server_ip, map_server_id, map_server_pw, - map_server_db ,map_server_port, (char *)NULL, 0)) { - printf("%s\n",mysql_error(&mail_handle)); - exit(1); - } - } - - return 0; -} - -int map_sql_close(void){ - mysql_close(&mmysql_handle); - printf("Close Map DB Connection....\n"); - - mysql_close(&lmysql_handle); - printf("Close Login DB Connection....\n"); - return 0; -} - -int log_sql_init(void){ - - mysql_init(&mmysql_handle); - - //DB connection start - printf("\033[1;29m[SQL]\033[0;0m: Connecting to Log Database \033[1;29m%s\033[0;0m At \033[1;29m%s\033[0;0m...\n",log_db,log_db_ip); - if(!mysql_real_connect(&mmysql_handle, log_db_ip, log_db_id, log_db_pw, - log_db ,log_db_port, (char *)NULL, 0)) { - //pointer check - printf("\033[1;29m[SQL Error]\033[0;0m: %s\n",mysql_error(&mmysql_handle)); - exit(1); - } else { - printf("\033[1;29m[SQL]\033[0;0m: Successfully \033[1;32mconnected\033[0;0m to Database \033[1;29m%s\033[0;0m.\n", log_db); - } - - return 0; -} - -int sql_config_read(char *cfgName) +int inter_config_read(char *cfgName) { int i; char line[1024],w1[1024],w2[1024]; @@ -1966,7 +2913,8 @@ int sql_config_read(char *cfgName) fp=fopen(cfgName,"r"); if(fp==NULL){ - printf("file not found: %s\n",cfgName); + snprintf(tmp_output,sizeof(tmp_output),"File not found: '%s'.\n",cfgName); + ShowError(tmp_output); return 1; } while(fgets(line,1020,fp)){ @@ -1975,7 +2923,11 @@ int sql_config_read(char *cfgName) i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2); if(i!=2) continue; - if(strcmpi(w1,"item_db_db")==0){ + //support the import command, just like any other config + if(strcmpi(w1,"import")==0){ + inter_config_read(w2); + #ifndef TXT_ONLY + } else if(strcmpi(w1,"item_db_db")==0){ strcpy(item_db_db,w2); } else if(strcmpi(w1,"mob_db_db")==0){ strcpy(mob_db_db,w2); @@ -1996,45 +2948,32 @@ int sql_config_read(char *cfgName) //Map Server SQL DB } else if(strcmpi(w1,"map_server_ip")==0){ strcpy(map_server_ip, w2); - printf ("set map_server_ip : %s\n",w2); } else if(strcmpi(w1,"map_server_port")==0){ map_server_port=atoi(w2); - printf ("set map_server_port : %s\n",w2); } else if(strcmpi(w1,"map_server_id")==0){ strcpy(map_server_id, w2); - printf ("set map_server_id : %s\n",w2); } else if(strcmpi(w1,"map_server_pw")==0){ strcpy(map_server_pw, w2); - printf ("set map_server_pw : %s\n",w2); } else if(strcmpi(w1,"map_server_db")==0){ strcpy(map_server_db, w2); - printf ("set map_server_db : %s\n",w2); - //Map server option to use SQL db or not } else if(strcmpi(w1,"use_sql_db")==0){ - if (strcmpi(w2,"yes")){db_use_sqldbs=0;} else if (strcmpi(w2,"no")){db_use_sqldbs=1;} + db_use_sqldbs = battle_config_switch(w2); printf ("Using SQL dbs: %s\n",w2); //Login Server SQL DB } else if(strcmpi(w1,"login_server_ip")==0){ strcpy(login_server_ip, w2); - printf ("set login_server_ip : %s\n",w2); } else if(strcmpi(w1,"login_server_port")==0){ login_server_port = atoi(w2); - printf ("set login_server_port : %s\n",w2); } else if(strcmpi(w1,"login_server_id")==0){ strcpy(login_server_id, w2); - printf ("set login_server_id : %s\n",w2); } else if(strcmpi(w1,"login_server_pw")==0){ strcpy(login_server_pw, w2); - printf ("set login_server_pw : %s\n",w2); } else if(strcmpi(w1,"login_server_db")==0){ strcpy(login_server_db, w2); - printf ("set login_server_db : %s\n",w2); } else if(strcmpi(w1,"lowest_gm_level")==0){ lowest_gm_level = atoi(w2); - printf ("set lowest_gm_level : %s\n",w2); } else if(strcmpi(w1,"read_gm_interval")==0){ read_gm_interval = ( atoi(w2) * 60 * 1000 ); // Minutes multiplied by 60 secs per min by 1000 milliseconds per second - printf ("set read_gm_interval : %s\n",w2); } else if(strcmpi(w1,"log_db")==0) { strcpy(log_db, w2); } else if(strcmpi(w1,"log_db_ip")==0) { @@ -2047,9 +2986,7 @@ int sql_config_read(char *cfgName) strcpy(log_db_pw, w2); } else if(strcmpi(w1,"log_db_port")==0) { log_db_port = atoi(w2); - //support the import command, just like any other config - } else if(strcmpi(w1,"import")==0){ - sql_config_read(w2); + #endif } } fclose(fp); @@ -2057,63 +2994,100 @@ int sql_config_read(char *cfgName) return 0; } -// sql online status checking [Valaris] -void char_offline(struct map_session_data *sd) -{ - if(sd && sd->status.char_id) { - sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `char_id`='%d'", char_db, sd->status.char_id); - if(mysql_query(&mmysql_handle, tmp_sql) ) { - printf("DB server Error (update online `%s`)- %s\n", char_db, mysql_error(&mmysql_handle) ); - } +#ifndef TXT_ONLY +/*======================================= + * MySQL Init + *--------------------------------------- + */ + +int map_sql_init(void){ + + mysql_init(&mmysql_handle); + + //DB connection start + printf("Connect Map DB Server....\n"); + if(!mysql_real_connect(&mmysql_handle, map_server_ip, map_server_id, map_server_pw, + map_server_db ,map_server_port, (char *)NULL, 0)) { + //pointer check + printf("%s\n",mysql_error(&mmysql_handle)); + exit(1); + } + else { + printf ("connect success! (Map Server Connection)\n"); } -} -void do_reset_online(void) -{ - sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `online`='1'", char_db); - if(mysql_query(&mmysql_handle, tmp_sql) ) { - printf("DB server Error (reset_online `%s`)- %s\n", char_db, mysql_error(&mmysql_handle) ); + mysql_init(&lmysql_handle); + + //DB connection start + printf("Connect Login DB Server....\n"); + if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw, + login_server_db ,login_server_port, (char *)NULL, 0)) { + //pointer check + printf("%s\n",mysql_error(&lmysql_handle)); + exit(1); + } + else { + printf ("connect success! (Login Server Connection)\n"); + } + + if(battle_config.mail_system) { // mail system [Valaris] + mysql_init(&mail_handle); + if(!mysql_real_connect(&mail_handle, map_server_ip, map_server_id, map_server_pw, + map_server_db ,map_server_port, (char *)NULL, 0)) { + printf("%s\n",mysql_error(&mail_handle)); + exit(1); + } } + + return 0; } -int online_timer(int tid,unsigned int tick,int id,int data) -{ - if(check_online_timer != tid) - return 0; +int map_sql_close(void){ + mysql_close(&mmysql_handle); + printf("Close Map DB Connection....\n"); - char_online_check(); + mysql_close(&lmysql_handle); + printf("Close Login DB Connection....\n"); + return 0; +} + +int log_sql_init(void){ + + mysql_init(&mmysql_handle); - check_online_timer=add_timer(gettick()+CHECK_INTERVAL,online_timer,0,0); + //DB connection start + printf(""CL_WHITE"[SQL]"CL_RESET": Connecting to Log Database "CL_WHITE"%s"CL_RESET" At "CL_WHITE"%s"CL_RESET"...\n",log_db,log_db_ip); + if(!mysql_real_connect(&mmysql_handle, log_db_ip, log_db_id, log_db_pw, + log_db ,log_db_port, (char *)NULL, 0)) { + //pointer check + printf(""CL_WHITE"[SQL Error]"CL_RESET": %s\n",mysql_error(&mmysql_handle)); + exit(1); + } else { + printf(""CL_WHITE"[SQL]"CL_RESET": Successfully '"CL_GREEN"connected"CL_RESET"' to Database '"CL_WHITE"%s"CL_RESET"'.\n", log_db); + } return 0; } +int online_timer (int tid,unsigned int tick,int id,int data) +{ + char_online_check(); + return 0; +} void char_online_check(void) { int i; - struct map_session_data *sd=NULL; - - do_reset_online(); + struct map_session_data *sd; - for(i=0;i<fd_max;i++){ - if (session[i] && (sd = session[i]->session_data) && sd && sd->state.auth && - !(battle_config.hide_GM_session && pc_isGM(sd))) - if(sd->status.char_id) { - sprintf(tmp_sql,"UPDATE `%s` SET `online`='1' WHERE `char_id`='%d'", char_db, sd->status.char_id); - if(mysql_query(&mmysql_handle, tmp_sql) ) { - printf("DB server Error (update online `%s`)- %s\n", char_db, mysql_error(&mmysql_handle) ); - } - } - } + chrif_char_reset_offline(); - - if(check_online_timer && check_online_timer != -1) { - delete_timer(check_online_timer,online_timer); - add_timer(gettick()+CHECK_INTERVAL,online_timer,0,0); + for (i = 0; i < fd_max; i++) { + if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd->state.auth && + !(battle_config.hide_GM_session && pc_isGM(sd))) + if(sd->status.char_id) + chrif_char_online(sd); } - } - #endif /* not TXT_ONLY */ //----------------------------------------------------- @@ -2135,23 +3109,32 @@ int flush_timer(int tid, unsigned int tick, int id, int data){ return 0; } -int id_db_final(void *k,void *d,va_list ap){ return 0; } -int map_db_final(void *k,void *d,va_list ap){ return 0; } -int nick_db_final(void *k,void *d,va_list ap){ return 0; } -int charid_db_final(void *k,void *d,va_list ap){ return 0; } - -static int cleanup_sub(struct block_list *bl, va_list ap) { +int id_db_final(void *k,void *d,va_list ap) { return 0; } +int map_db_final(void *k,void *d,va_list ap) { return 0; } +int nick_db_final(void *k,void *d,va_list ap) +{ + char *p = (char *) d; + if (p) aFree(p); + return 0; +} +int charid_db_final(void *k,void *d,va_list ap) +{ + struct charid2nick *p = (struct charid2nick *) d; + if (p) aFree(p); + return 0; +} +int cleanup_sub(struct block_list *bl, va_list ap) { nullpo_retr(0, bl); switch(bl->type) { case BL_PC: - map_delblock(bl); // There is something better... + map_quit((struct map_session_data *) bl); break; case BL_NPC: - npc_delete((struct npc_data *)bl); + npc_unload((struct npc_data *)bl); break; case BL_MOB: - mob_delete((struct mob_data *)bl); + mob_unload((struct mob_data *)bl); break; case BL_PET: pet_remove_map((struct map_session_data *)bl); @@ -2168,47 +3151,100 @@ static int cleanup_sub(struct block_list *bl, va_list ap) { } /*========================================== - * mapŽII—¹Žžˆ— + * mapŽII—¹Žž?— *------------------------------------------ */ void do_final(void) { - int map_id, i; + int i; + ShowStatus("Terminating...\n"); - for (map_id = 0; map_id < map_num;map_id++) { - if(map[map_id].m) - map_foreachinarea(cleanup_sub, map_id, 0, 0, map[map_id].xs, map[map_id].ys, 0, 0); - } + for (i = 0; i < map_num; i++) + if(map[i].m) + map_foreachinarea(cleanup_sub, i, 0, 0, map[i].xs, map[i].ys, 0, 0); - for (i = 0; i < fd_max; i++) - delete_session(i); +#ifndef TXT_ONLY + chrif_char_reset_offline(); +#endif - map_removenpc(); - timer_final(); + chrif_flush_fifo(); + +//#if 0 // why is this here? >_> + do_final_chrif(); // ‚±‚Ì“à•”‚ŃLƒƒƒ‰‚ð‘S‚ÄØ’f‚·‚é + do_final_npc(); +// map_removenpc(); + do_final_script(); + do_final_itemdb(); + do_final_storage(); + do_final_guild(); + do_final_party(); + do_final_pc(); + do_final_pet(); + do_final_msg(); + + for (i=0; i<map_num; i++) { + if(map[i].gat) aFree(map[i].gat); + if(map[i].block) aFree(map[i].block); + if(map[i].block_mob) aFree(map[i].block_mob); + if(map[i].block_count) aFree(map[i].block_count); + if(map[i].block_mob_count) aFree(map[i].block_mob_count); + } +// do_final_timer(); (we used timer_final() instead) + timer_final(); numdb_final(id_db, id_db_final); - strdb_final(map_db, map_db_final); + strdb_final(map_db, map_db_final); strdb_final(nick_db, nick_db_final); numdb_final(charid_db, charid_db_final); + exit_dbn(); + +//#endif - for(i=0;i<=map_num;i++){ - if(map[i].gat) free(map[i].gat); - if(map[i].block) free(map[i].block); - if(map[i].block_mob) free(map[i].block_mob); - if(map[i].block_count) free(map[i].block_count); - if(map[i].block_mob_count) free(map[i].block_mob_count); - } - do_final_script(); - do_final_itemdb(); - do_final_storage(); - do_final_guild(); #ifndef TXT_ONLY - do_reset_online(); map_sql_close(); #endif /* not TXT_ONLY */ + ShowStatus("Successfully terminated.\n"); } -void map_helpscreen() { - exit(1); +/*====================================================== + * Map-Server Version Screen [MC Cameri] + *------------------------------------------------------ + */ +void map_helpscreen(int flag) { // by MC Cameri + puts("Usage: map-server [options]"); + puts("Options:"); + puts(CL_WHITE" Commands\t\t\tDescription"CL_RESET); + puts("-----------------------------------------------------------------------------"); + puts(" --help, --h, --?, /? Displays this help screen"); + puts(" --map-config <file> Load map-server configuration from <file>"); + puts(" --battle-config <file> Load battle configuration from <file>"); + puts(" --atcommand-config <file> Load atcommand configuration from <file>"); + puts(" --charcommand-config <file> Load charcommand configuration from <file>"); + puts(" --script-config <file> Load script configuration from <file>"); + puts(" --msg-config <file> Load message configuration from <file>"); + puts(" --grf-path-file <file> Load grf path file configuration from <file>"); + puts(" --sql-config <file> Load inter-server configuration from <file>"); + puts(" (SQL Only)"); + puts(" --log-config <file> Load logging configuration from <file>"); + puts(" (SQL Only)"); + puts(" --version, --v, -v, /v Displays the server's version"); + puts("\n"); + if (flag) exit(1); +} + +/*====================================================== + * Map-Server Version Screen [MC Cameri] + *------------------------------------------------------ + */ +void map_versionscreen(int flag) { + printf("CL_WHITE" "eAthena version %d.%02d.%02d, Athena Mod version %d" CL_RESET"\n", + ATHENA_MAJOR_VERSION, ATHENA_MINOR_VERSION, ATHENA_REVISION, + ATHENA_MOD_VERSION); + puts(CL_GREEN "Website/Forum:" CL_RESET "\thttp://eathena.deltaanime.net/"); + puts(CL_GREEN "Download URL:" CL_RESET "\thttp://eathena.systeminplace.net/"); + puts(CL_GREEN "IRC Channel:" CL_RESET "\tirc://irc.deltaanime.net/#athena"); + puts("\nOpen " CL_WHITE "readme.html" CL_RESET " for more information."); + if (ATHENA_RELEASE_FLAG) ShowNotice("This version is not for release.\n"); + if (flag) exit(1); } /*====================================================== @@ -2220,42 +3256,52 @@ int do_init(int argc, char *argv[]) { FILE *data_conf; char line[1024], w1[1024], w2[1024]; -#ifndef TXT_ONLY - unsigned char *SQL_CONF_NAME="conf/inter_athena.conf"; - unsigned char *LOG_CONF_NAME="conf/log_athena.conf"; + SERVER_TYPE = SERVER_MAP; +#ifdef GCOLLECT + GC_enable_incremental(); #endif - unsigned char *MAP_CONF_NAME = "conf/map_athena.conf"; - unsigned char *BATTLE_CONF_FILENAME = "conf/battle_athena.conf"; - unsigned char *ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf"; - unsigned char *CHARCOMMAND_CONF_FILENAME = "conf/charcommand_athena.conf"; - unsigned char *SCRIPT_CONF_NAME = "conf/script_athena.conf"; - unsigned char *MSG_CONF_NAME = "conf/msg_athena.conf"; - unsigned char *GRF_PATH_FILENAME = "conf/grf-files.txt"; + + INTER_CONF_NAME="conf/inter_athena.conf"; + LOG_CONF_NAME="conf/log_athena.conf"; + MAP_CONF_NAME = "conf/map_athena.conf"; + BATTLE_CONF_FILENAME = "conf/battle_athena.conf"; + ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf"; + CHARCOMMAND_CONF_FILENAME = "conf/charcommand_athena.conf"; + SCRIPT_CONF_NAME = "conf/script_athena.conf"; + MSG_CONF_NAME = "conf/msg_athena.conf"; + GRF_PATH_FILENAME = "conf/grf-files.txt"; + + chrif_connected = 0; srand(gettick()); for (i = 1; i < argc ; i++) { - if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "--h") == 0 || strcmp(argv[i], "--?") == 0 || strcmp(argv[i], "/?") == 0) - map_helpscreen(); - else if (strcmp(argv[i], "--map_config") == 0) + map_helpscreen(1); + if (strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "--v") == 0 || strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "/v") == 0) + map_versionscreen(1); + else if (strcmp(argv[i], "--map_config") == 0 || strcmp(argv[i], "--map-config") == 0) MAP_CONF_NAME=argv[i+1]; - else if (strcmp(argv[i],"--battle_config") == 0) + else if (strcmp(argv[i],"--battle_config") == 0 || strcmp(argv[i],"--battle-config") == 0) BATTLE_CONF_FILENAME = argv[i+1]; - else if (strcmp(argv[i],"--atcommand_config") == 0) + else if (strcmp(argv[i],"--atcommand_config") == 0 || strcmp(argv[i],"--atcommand-config") == 0) ATCOMMAND_CONF_FILENAME = argv[i+1]; - else if (strcmp(argv[i],"--charcommand_config") == 0) + else if (strcmp(argv[i],"--charcommand_config") == 0 || strcmp(argv[i],"--charcommand-config") == 0) CHARCOMMAND_CONF_FILENAME = argv[i+1]; - else if (strcmp(argv[i],"--script_config") == 0) + else if (strcmp(argv[i],"--script_config") == 0 || strcmp(argv[i],"--script-config") == 0) SCRIPT_CONF_NAME = argv[i+1]; - else if (strcmp(argv[i],"--msg_config") == 0) + else if (strcmp(argv[i],"--msg_config") == 0 || strcmp(argv[i],"--msg-config") == 0) MSG_CONF_NAME = argv[i+1]; - else if (strcmp(argv[i],"--grf_path_file") == 0) + else if (strcmp(argv[i],"--grf_path_file") == 0 || strcmp(argv[i],"--grf-path-file") == 0) GRF_PATH_FILENAME = argv[i+1]; #ifndef TXT_ONLY - else if (strcmp(argv[i],"--sql_config") == 0) - SQL_CONF_NAME = argv[i+1]; + else if (strcmp(argv[i],"--inter_config") == 0 || strcmp(argv[i],"--inter-config") == 0) + INTER_CONF_NAME = argv[i+1]; #endif /* not TXT_ONLY */ + else if (strcmp(argv[i],"--log_config") == 0 || strcmp(argv[i],"--log-config") == 0) + LOG_CONF_NAME = argv[i+1]; + else if (strcmp(argv[i],"--run_once") == 0) // close the map-server as soon as its done.. for testing [Celest] + runflag = 0; } map_config_read(MAP_CONF_NAME); @@ -2285,16 +3331,14 @@ int do_init(int argc, char *argv[]) { if (ptr[0] == 192 && ptr[1] == 168) printf("\nFirewall detected.. \n edit lan_support.conf and map_athena.conf\n\n"); } - + if (SHOW_DEBUG_MSG) ShowNotice("Server running in '"CL_WHITE"Debug Mode"CL_RESET"'.\n"); battle_config_read(BATTLE_CONF_FILENAME); msg_config_read(MSG_CONF_NAME); atcommand_config_read(ATCOMMAND_CONF_FILENAME); charcommand_config_read(CHARCOMMAND_CONF_FILENAME); script_config_read(SCRIPT_CONF_NAME); -#ifndef TXT_ONLY - sql_config_read(SQL_CONF_NAME); + inter_config_read(INTER_CONF_NAME); log_config_read(LOG_CONF_NAME); -#endif /* not TXT_ONLY */ atexit(do_final); @@ -2323,45 +3367,48 @@ int do_init(int argc, char *argv[]) { map_readallmap(); + add_timer_func_list(map_freeblock_timer,"map_freeblock_timer"); add_timer_func_list(map_clearflooritem_timer, "map_clearflooritem_timer"); + add_timer_interval(gettick()+1000,map_freeblock_timer,0,0,60*1000); //Added by Mugendai for GUI support if (flush_on) - { add_timer_interval(gettick()+10, flush_timer,0,0,flush_time); - } + //Added for Mugendais I'm Alive mod + if (imalive_on) + add_timer_interval(gettick()+10, imalive_timer,0,0,imalive_time*1000); #ifndef TXT_ONLY // online status timer, checks every hour [Valaris] add_timer_func_list(online_timer, "online_timer"); - check_online_timer=add_timer(gettick()+CHECK_INTERVAL,online_timer,0,0); + add_timer_interval(gettick()+10, online_timer, 0, 0, CHECK_INTERVAL); #endif /* not TXT_ONLY */ do_init_chrif(); do_init_clif(); do_init_itemdb(); - do_init_mob(); // npc‚̉Šú‰»Žž“à‚Åmob_spawn‚µ‚ÄAmob_db‚ðŽQÆ‚·‚é‚Ì‚Åinit_npc‚æ‚èæ + do_init_mob(); // npc‚̉Šú‰»Žž?‚Åmob_spawn‚µ‚ÄAmob_db‚ð?Æ‚·‚é‚Ì‚Åinit_npc‚æ‚èæ do_init_script(); - do_init_npc(); do_init_pc(); + do_init_status(); do_init_party(); do_init_guild(); do_init_storage(); do_init_skill(); do_init_pet(); + do_init_npc(); #ifndef TXT_ONLY /* mail system [Valaris] */ if(battle_config.mail_system) do_init_mail(); - if (log_config.branch || log_config.drop || log_config.mvpdrop || - log_config.present || log_config.produce || log_config.refine || - log_config.trade) + if (log_config.sql_logs && (log_config.branch || log_config.drop || log_config.mvpdrop || + log_config.present || log_config.produce || log_config.refine || log_config.trade)) { log_sql_init(); } #endif /* not TXT_ONLY */ - npc_event_do_oninit(); // npc‚ÌOnInitƒCƒxƒ“ƒgŽÀs + npc_event_do_oninit(); // npc‚ÌOnInitƒCƒxƒ“ƒg?s if ( console ) { set_defaultconsoleparse(parse_console); @@ -2369,15 +3416,22 @@ int do_init(int argc, char *argv[]) { } if (battle_config.pk_mode == 1) - printf("The server is running in \033[1;31mPK Mode\033[0m.\n"); - - //Added for Mugendais I'm Alive mod - if (imalive_on) - add_timer_interval(gettick()+10, imalive_timer,0,0,imalive_time*1000); - - printf("The map-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n", map_port); - ticks = gettick(); + ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n"); + sprintf(tmp_output,"Server is '"CL_GREEN"ready"CL_RESET"' and listening on port '"CL_WHITE"%d"CL_RESET"'.\n\n", map_port); + ShowStatus(tmp_output); return 0; } + +int compare_item(struct item *a, struct item *b) { + return ( + (a->nameid == b->nameid) && + (a->identify == b->identify) && + (a->refine == b->refine) && + (a->attribute == b->attribute) && + (a->card[0] == b->card[0]) && + (a->card[1] == b->card[1]) && + (a->card[2] == b->card[2]) && + (a->card[3] == b->card[3])); +} diff --git a/src/map/map.h b/src/map/map.h index bf443bf46..01d9fef0e 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -10,7 +10,7 @@ #define PC_CLASS_BASE2 (PC_CLASS_BASE + 4001) #define PC_CLASS_BASE3 (PC_CLASS_BASE2 + 22) #define MAX_NPC_PER_MAP 512 -#define BLOCK_SIZE 8 +#define BLOCK_SIZE 8 // Never zero #define AREA_SIZE battle_config.area_size #define LOCAL_REG_NUM 16 #define LIFETIME_FLOORITEM 60 @@ -20,7 +20,7 @@ #define MAX_STATUSCHANGE 210 #define MAX_SKILLUNITGROUP 32 #define MAX_MOBSKILLUNITGROUP 8 -#define MAX_SKILLUNITGROUPTICKSET 128 +#define MAX_SKILLUNITGROUPTICKSET 32 #define MAX_SKILLTIMERSKILL 32 #define MAX_MOBSKILLTIMERSKILL 10 #define MAX_MOBSKILL 32 @@ -32,6 +32,7 @@ #define MAX_WALKPATH 32 #define MAX_DROP_PER_MAP 48 #define MAX_IGNORE_LIST 80 +#define MAX_VENDING 12 #define DEFAULT_AUTOSAVE_INTERVAL 60*1000 @@ -52,6 +53,12 @@ struct walkpath_data { unsigned char path_len,path_pos,path_half; unsigned char path[MAX_WALKPATH]; }; +struct shootpath_data { + int rx,ry,len; + int x[MAX_WALKPATH]; + int y[MAX_WALKPATH]; +}; + struct script_reg { int index; int data; @@ -84,13 +91,13 @@ struct skill_unit_group { int src_id; int party_id; int guild_id; - int map,range; + int map; int target_flag; unsigned int tick; int limit,interval; int skill_id,skill_lv; - int val1,val2; + int val1,val2,val3; char *valstr; int unit_id; int group_id; @@ -99,7 +106,7 @@ struct skill_unit_group { }; struct skill_unit_group_tickset { unsigned int tick; - int group_id; + int id; }; struct skill_timerskill { int timer; @@ -137,6 +144,12 @@ struct map_session_data { unsigned make_arrow_flag : 1; unsigned potionpitcher_flag : 1; unsigned storage_flag : 1; + unsigned snovice_flag : 4; + int gmaster_flag; + // originally by Qamera, adapted by celest + unsigned event_death : 1; + unsigned event_kill : 1; + unsigned event_disconnect : 1; } state; struct { unsigned killer : 1; @@ -149,15 +162,14 @@ struct map_session_data { unsigned no_weapon_damage : 1; unsigned no_gemstone : 1; unsigned infinite_endure : 1; - unsigned unbreakable_weapon : 1; - unsigned unbreakable_armor : 1; - unsigned infinite_autospell : 1; } special_state; int char_id, login_id1, login_id2, sex; int packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) struct mmo_charstatus status; struct item_data *inventory_data[MAX_INVENTORY]; short equip_index[11]; + unsigned short unbreakable_equip; + unsigned short unbreakable; // chance to prevent equipment breaking [celest] int weight,max_weight; int cart_weight,cart_max_weight,cart_num,cart_max_num; char mapname[24]; @@ -169,6 +181,7 @@ struct map_session_data { unsigned int client_tick,server_tick; struct walkpath_data walkpath; int walktimer; + int next_walktime; int npc_id,areanpc_id,npc_shopid; int npc_pos; int npc_menu; @@ -178,6 +191,7 @@ struct map_session_data { char *npc_stackbuf; char npc_str[256]; unsigned int chatID; + unsigned long idletime; struct{ char name[24]; @@ -192,6 +206,8 @@ struct map_session_data { int followtimer; // [MouseJstr] int followtarget; + time_t emotionlasttime; // to limit flood with emotion packets + short attackrange,attackrange_; int skilltimer; int skilltarget; @@ -203,17 +219,21 @@ struct map_session_data { struct skill_unit_group skillunit[MAX_SKILLUNITGROUP]; struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET]; struct skill_timerskill skilltimerskill[MAX_SKILLTIMERSKILL]; - int cloneskill_id,cloneskill_lv; + char blockskill[MAX_SKILL]; // [celest] + //unsigned int skillstatictimer[MAX_SKILL]; + unsigned short timerskill_count; // [celest] + int cloneskill_id; int potion_hp,potion_sp,potion_per_hp,potion_per_sp; int invincible_timer; unsigned int canact_tick; unsigned int canmove_tick; unsigned int canlog_tick; + unsigned int canregen_tick; int hp_sub,sp_sub; int inchealhptick,inchealsptick,inchealspirithptick,inchealspiritsptick; // -- moonsoul (new tick for berserk self-damage) - int berserkdamagetick; +// int berserkdamagetick; int fame; short view_class; @@ -224,12 +244,13 @@ struct map_session_data { int watk,watk2,atkmods[3]; int def,def2,mdef,mdef2,critical,matk1,matk2; int atk_ele,def_ele,star,overrefine; - int castrate,hprate,sprate,dsprate; + int castrate,delayrate,hprate,sprate,dsprate; int addele[10],addrace[12],addsize[3],subele[10],subrace[12]; int addeff[10],addeff2[10],reseff[10]; int watk_,watk_2,atkmods_[3],addele_[10],addrace_[12],addsize_[3]; //“ñ“—¬‚Ì‚½‚߂ɒljÁ int atk_ele_,star_,overrefine_; //“ñ“—¬‚Ì‚½‚߂ɒljÁ int base_atk,atk_rate; + int weapon_atk[16],weapon_atk_rate[16]; int arrow_atk,arrow_ele,arrow_cri,arrow_hit,arrow_range; int arrow_addele[10],arrow_addrace[12],arrow_addsize[3],arrow_addeff[10],arrow_addeff2[10]; int nhealhp,nhealsp,nshealhp,nshealsp,nsshealhp,nsshealsp; @@ -258,18 +279,42 @@ struct map_session_data { short hp_drain_value,sp_drain_value,hp_drain_value_,sp_drain_value_; int short_weapon_damage_return,long_weapon_damage_return; int weapon_coma_ele[10],weapon_coma_race[12]; - short break_weapon_rate,break_armor_rate; + int break_weapon_rate,break_armor_rate; short add_steal_rate; + //--- 02/15's new card effects [celest] + int crit_atk_rate; + int critaddrace[12]; + short no_regen; + int addeff3[10]; + short addeff3_type[10]; + short autospell2_id,autospell2_lv,autospell2_rate,autospell2_type; + int skillatk[2]; + unsigned short unstripable_equip; + short add_damage_classid2[10],add_damage_class_count2; + int add_damage_classrate2[10]; + short sp_gain_value, hp_gain_value; + short sp_drain_type; + short ignore_def_mob, ignore_def_mob_; + int hp_loss_tick, hp_loss_rate; + short hp_loss_value, hp_loss_type; + int addrace2[12],addrace2_[12]; + int subsize[3]; + short unequip_losehp[11]; + short unequip_losesp[11]; + int itemid; + int itemhealrate[7]; + //--- 03/15's new card effects + int expaddrace[12]; + int subrace2[12]; + short sp_gain_race[12]; short spiritball, spiritball_old; int spirit_timer[MAX_SKILL_LEVEL]; int magic_damage_return; // AppleGirl Was Here int random_attack_increase_add,random_attack_increase_per; // [Valaris] int perfect_hiding; // [Valaris] - int unbreakable; int classchange; // [Valaris] - int die_counter; short doridori_counter; @@ -299,7 +344,7 @@ struct map_session_data { int vender_id; int vend_num; char message[80]; - struct vending vending[12]; + struct vending vending[MAX_VENDING]; int catch_target_class; struct s_pet pet; @@ -311,11 +356,15 @@ struct map_session_data { char eventqueue[MAX_EVENTQUEUE][50]; int eventtimer[MAX_EVENTTIMER]; + unsigned short eventcount; // [celest] int last_skillid,last_skilllv; // Added by RoVeRT - short sg_count; unsigned char change_level; // [celest] + int autoloot; //by Upa-Kun + unsigned nodelay :1; + unsigned noexp :1; + unsigned detach :1; #ifndef TXT_ONLY int mail_counter; // mail counter for mail system [Valaris] @@ -336,7 +385,7 @@ struct npc_item_list { struct npc_data { struct block_list bl; short n; - short class,dir; + short class_,dir; short speed; char name[24]; char exname[24]; @@ -360,7 +409,7 @@ struct npc_data { char *script; short xs,ys; int guild_id; - int timer,timerid,timeramount,nexttimer; + int timer,timerid,timeramount,nexttimer,rid; unsigned int timertick; struct npc_timerevent_list *timer_event; int label_list_num; @@ -379,11 +428,13 @@ struct npc_data { char eventqueue[MAX_EVENTQUEUE][50]; int eventtimer[MAX_EVENTTIMER]; short arenaflag; + + void *chatdb; }; struct mob_data { struct block_list bl; short n; - short base_class,class,dir,mode,level; + short base_class,class_,dir,mode,level; short m,x0,y0,xs,ys; char name[24]; int spawndelay1,spawndelay2; @@ -398,9 +449,12 @@ struct mob_data { unsigned change_walk_target : 1; unsigned walk_easy : 1; unsigned special_mob_ai : 3; + unsigned soul_change_flag : 1; // Celest + int provoke_flag; // Celest } state; int timer; short to_x,to_y; + short target_dir; short speed; int hp; int target_id,attacked_id; @@ -422,7 +476,6 @@ struct mob_data { short sc_count; short opt1,opt2,opt3,option; short min_chase; - short sg_count; int guild_id; int deletetimer; @@ -438,18 +491,22 @@ struct mob_data { struct skill_unit_group skillunit[MAX_MOBSKILLUNITGROUP]; struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET]; char npc_event[50]; - short size; + unsigned char size; + short recall_flag; + int recallmob_count; + short recallcount; }; struct pet_data { struct block_list bl; short n; - short class,dir; + short class_,dir; short speed; char name[24]; struct { unsigned state : 8 ; unsigned skillstate : 8 ; unsigned change_walk_target : 1 ; + short skillbonus; } state; int timer; short to_x,to_y; @@ -460,7 +517,8 @@ struct pet_data { int move_fail_count; unsigned int attackabletime,next_walktime,last_thinktime; int skilltype,skillval,skilltimer,skillduration; // [Valaris] - int skillbonustype,skillbonusval,skillbonustimer,skillbonusduration; // [Valaris] + //int skillbonustype,skillbonusval,skillbonustimer,skillbonusduration; // [Valaris] + int skillbonustype,skillbonusval,skillbonustimer; struct item *lootitem; short loot; // [Valaris] short lootmax; // [Valaris] @@ -479,10 +537,18 @@ enum { NONE_ATTACKABLE,ATTACKABLE }; enum { ATK_LUCKY=1,ATK_FLEE,ATK_DEF}; // ˆÍ‚Ü‚êƒyƒiƒ‹ƒeƒBŒvŽZ—p +// ‘•”õƒR[ƒh +enum { + EQP_WEAPON = 0x0002, // ‰EŽè + EQP_ARMOR = 0x0010, // ‘Ì + EQP_SHIELD = 0x0020, // ¶Žè + EQP_HELM = 0x0100, // “ªã’i +}; + struct map_data { char name[24]; - char alias[24]; // [MouseJstr] unsigned char *gat; // NULL‚Ȃ牺‚Ìmap_data_other_server‚Æ‚µ‚Ĉµ‚¤ + char *alias; // [MouseJstr] struct block_list **block; struct block_list **block_mob; int *block_count,*block_mob_count; @@ -535,9 +601,8 @@ struct map_data_other_server { unsigned char *gat; // NULLŒÅ’è‚É‚µ‚Ä”»’f unsigned long ip; unsigned int port; + struct map_data* map; }; -#define read_gat(m,x,y) (map[m].gat[(x)+(y)*map[m].xs]) -#define read_gatp(m,x,y) (m->gat[(x)+(y)*m->xs]) struct flooritem_data { struct block_list bl; @@ -556,7 +621,7 @@ enum { SP_USTR,SP_UAGI,SP_UVIT,SP_UINT,SP_UDEX,SP_ULUK,SP_26,SP_27, // 32-39 SP_28,SP_ATK1,SP_ATK2,SP_MATK1,SP_MATK2,SP_DEF1,SP_DEF2,SP_MDEF1, // 40-47 SP_MDEF2,SP_HIT,SP_FLEE1,SP_FLEE2,SP_CRITICAL,SP_ASPD,SP_36,SP_JOBLEVEL, // 48-55 - SP_UPPER,SP_PARTNER,SP_CART,SP_FAME,SP_UNBREAKABLE, //56-58 + SP_UPPER,SP_PARTNER,SP_CART,SP_FAME,SP_UNBREAKABLE, //56-60 SP_CARTINFO=99, // 99 SP_BASEJOB=119, // 100+19 - celest @@ -584,15 +649,51 @@ enum { SP_MAGIC_DAMAGE_RETURN,SP_RANDOM_ATTACK_INCREASE,SP_ALL_STATS,SP_AGI_VIT,SP_AGI_DEX_STR,SP_PERFECT_HIDE, // 1071-1076 SP_DISGUISE,SP_CLASSCHANGE, // 1077-1078 SP_HP_DRAIN_VALUE,SP_SP_DRAIN_VALUE, // 1079-1080 - + SP_WEAPON_ATK,SP_WEAPON_ATK_RATE, // 1081-1082 + SP_DELAYRATE, // 1083 + SP_RESTART_FULL_RECORVER=2000,SP_NO_CASTCANCEL,SP_NO_SIZEFIX,SP_NO_MAGIC_DAMAGE,SP_NO_WEAPON_DAMAGE,SP_NO_GEMSTONE, // 2000-2005 - SP_NO_CASTCANCEL2,SP_INFINITE_ENDURE,SP_UNBREAKABLE_WEAPON,SP_UNBREAKABLE_ARMOR // 2006-2009 + SP_NO_CASTCANCEL2,SP_INFINITE_ENDURE,SP_UNBREAKABLE_WEAPON,SP_UNBREAKABLE_ARMOR, SP_UNBREAKABLE_HELM, // 2006-2010 + SP_UNBREAKABLE_SHIELD, SP_LONG_ATK_RATE, // 2011-2012 + + SP_CRIT_ATK_RATE, SP_CRITICAL_ADDRACE, SP_NO_REGEN, SP_ADDEFF_WHENHIT, SP_AUTOSPELL_WHENHIT, // 2013-2017 + SP_SKILL_ATK, SP_UNSTRIPABLE, SP_ADD_DAMAGE_BY_CLASS, // 2018-2020 + SP_SP_GAIN_VALUE, SP_IGNORE_DEF_MOB, SP_HP_LOSS_RATE, SP_ADDRACE2, SP_HP_GAIN_VALUE, // 2021-2025 + SP_SUBSIZE, SP_DAMAGE_WHEN_UNEQUIP, SP_ADD_ITEM_HEAL_RATE, SP_LOSESP_WHEN_UNEQUIP, SP_EXP_ADDRACE, // 2026-2030 + SP_SP_GAIN_RACE, SP_SUBRACE2, SP_ADDEFF_WHENHIT_SHORT, // 2031-2033 + SP_UNSTRIPABLE_WEAPON,SP_UNSTRIPABLE_ARMOR,SP_UNSTRIPABLE_HELM,SP_UNSTRIPABLE_SHIELD // 2034-2037 }; enum { LOOK_BASE,LOOK_HAIR,LOOK_WEAPON,LOOK_HEAD_BOTTOM,LOOK_HEAD_TOP,LOOK_HEAD_MID,LOOK_HAIR_COLOR,LOOK_CLOTHES_COLOR,LOOK_SHIELD,LOOK_SHOES }; +// CELL +#define CELL_MASK 0x0f +#define CELL_NPC 0x80 // NPCƒZƒ‹ +#define CELL_BASILICA 0x40 // BASILICAƒZƒ‹ +#define CELL_MOONLIT 0x100 +#define CELL_REGEN 0x200 +/* + * map_getcell()‚ÅŽg—p‚³‚ê‚éƒtƒ‰ƒO + */ +typedef enum { + CELL_CHKWALL=0, // •Ç(ƒZƒ‹ƒ^ƒCƒv1) + CELL_CHKWATER, // …ê(ƒZƒ‹ƒ^ƒCƒv3) + CELL_CHKGROUND, // ’n–ÊáŠQ•¨(ƒZƒ‹ƒ^ƒCƒv5) + CELL_CHKPASS, // ’ʉ߉”\(ƒZƒ‹ƒ^ƒCƒv1,5ˆÈŠO) + CELL_CHKNOPASS, // ’ʉߕs‰Â(ƒZƒ‹ƒ^ƒCƒv1,5) + CELL_GETTYPE, // ƒZƒ‹ƒ^ƒCƒv‚ð•Ô‚· + CELL_CHKNPC=0x10, // ƒ^ƒbƒ`ƒ^ƒCƒv‚ÌNPC(ƒZƒ‹ƒ^ƒCƒv0x80ƒtƒ‰ƒO) + CELL_CHKBASILICA, // ƒoƒWƒŠƒJ(ƒZƒ‹ƒ^ƒCƒv0x40ƒtƒ‰ƒO) +} cell_t; +// map_setcell()‚ÅŽg—p‚³‚ê‚éƒtƒ‰ƒO +enum { + CELL_SETNPC=0x10, // ƒ^ƒbƒ`ƒ^ƒCƒv‚ÌNPC‚ðƒZƒbƒg + CELL_SETBASILICA, // ƒoƒWƒŠƒJ‚ðƒZƒbƒg + CELL_CLRBASILICA, // ƒoƒWƒŠƒJ‚ðƒNƒŠƒA +}; + struct chat_data { struct block_list bl; @@ -614,6 +715,17 @@ extern int autosave_interval; extern int agit_flag; extern int night_flag; // 0=day, 1=night [Yor] +// gat?Ö§ +int map_getcell(int,int,int,cell_t); +int map_getcellp(struct map_data*,int,int,cell_t); +void map_setcell(int,int,int,int); +extern int map_read_flag; // 0: grf«Õ«¡«¤«ë 1: ««ã«Ã«·«å 2: ««ã«Ã«·«å(?õê) +enum { + READ_FROM_GAT, READ_FROM_AFM, + READ_FROM_BITMAP, CREATE_BITMAP, + READ_FROM_BITMAP_COMPRESSED, CREATE_BITMAP_COMPRESSED +}; + extern char motd_txt[]; extern char help_txt[]; @@ -635,9 +747,11 @@ void map_foreachinarea(int (*)(struct block_list*,va_list),int,int,int,int,int,i // -- moonsoul (added map_foreachincell) void map_foreachincell(int (*)(struct block_list*,va_list),int,int,int,int,...); void map_foreachinmovearea(int (*)(struct block_list*,va_list),int,int,int,int,int,int,int,int,...); +void map_foreachinpath(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int range,int type,...); // Celest int map_countnearpc(int,int,int); //blockŠÖ˜A‚ɒljÁ int map_count_oncell(int m,int x,int y); +struct skill_unit *map_find_skill_unit_oncell(struct block_list *,int x,int y,int skill_id,struct skill_unit *); // ˆêŽž“IobjectŠÖ˜A int map_addobject(struct block_list *); int map_delobject(int); @@ -659,6 +773,7 @@ void map_addchariddb(int charid,char *name); void map_delchariddb(int charid); int map_reqchariddb(struct map_session_data * sd,int charid); char * map_charid2nick(int); +struct map_session_data * map_charid2sd(int); struct map_session_data * map_id2sd(int); struct block_list * map_id2bl(int); @@ -666,15 +781,13 @@ int map_mapname2mapid(char*); int map_mapname2ipport(char*,int*,int*); int map_setipport(char *name,unsigned long ip,int port); int map_eraseipport(char *name,unsigned long ip,int port); +int map_eraseallipport(void); void map_addiddb(struct block_list *); void map_deliddb(struct block_list *bl); int map_foreachiddb(int (*)(void*,void*,va_list),...); void map_addnickdb(struct map_session_data *); struct map_session_data * map_nick2sd(char*); - -// gatŠÖ˜A -int map_getcell(int,int,int); -int map_setcell(int,int,int,int); +int compare_item(struct item *a, struct item *b); // ‚»‚Ì‘¼ int map_check_dir(int s_dir,int t_dir); @@ -682,18 +795,33 @@ int map_calc_dir( struct block_list *src,int x,int y); // path.c‚æ‚è int path_search(struct walkpath_data*,int,int,int,int,int,int); +int path_search_long(struct shootpath_data *,int,int,int,int,int); int path_blownpos(int m,int x0,int y0,int dx,int dy,int count); int map_who(int fd); +int cleanup_sub(struct block_list *bl, va_list ap); + void map_helpscreen(); // [Valaris] int map_delmap(char *mapname); -extern unsigned long ticks; +extern char *INTER_CONF_NAME; +extern char *LOG_CONF_NAME; +extern char *MAP_CONF_NAME; +extern char *BATTLE_CONF_FILENAME; +extern char *ATCOMMAND_CONF_FILENAME; +extern char *CHARCOMMAND_CONF_FILENAME; +extern char *SCRIPT_CONF_NAME; +extern char *MSG_CONF_NAME; +extern char *GRF_PATH_FILENAME; #ifndef TXT_ONLY // MySQL +#ifdef __WIN32 +#include <my_global.h> +#include <my_sys.h> +#endif #include <mysql.h> void char_online_check(void); // [Valaris] diff --git a/src/map/mob.c b/src/map/mob.c index ef67341f8..f076b7530 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -13,6 +13,7 @@ #include "clif.h" #include "intif.h" #include "pc.h" +#include "status.h" #include "mob.h" #include "guild.h" #include "itemdb.h" @@ -21,6 +22,7 @@ #include "party.h" #include "npc.h" #include "log.h" +#include "showmsg.h" #ifdef MEMWATCH #include "memwatch.h" @@ -31,7 +33,9 @@ #define MOB_LAZYMOVEPERC 50 // Move probability in the negligent mode MOB (rate of 1000 minute) #define MOB_LAZYWARPPERC 20 // Warp probability in the negligent mode MOB (rate of 1000 minute) -struct mob_db mob_db[2001]; +struct mob_db mob_db[MAX_MOB_DB+1]; + +#define CLASSCHANGE_BOSS_NUM 21 /*========================================== * Local prototype declaration (only required thing) @@ -42,7 +46,7 @@ static int mob_makedummymobdb(int); static int mob_timer(int,unsigned int,int,int); int mobskill_use(struct mob_data *md,unsigned int tick,int event); int mobskill_deltimer(struct mob_data *md ); -int mob_skillid2skillidx(int class,int skillid); +int mob_skillid2skillidx(int class_,int skillid); int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx); static int mob_unlocktarget(struct mob_data *md,int tick); @@ -67,7 +71,7 @@ int mobdb_searchname(const char *str) * Id Mob is checked. *------------------------------------------ */ -int mobdb_checkid(const int id) +int mobdb_checkid(const int id) { if (id <= 0 || id >= (sizeof(mob_db) / sizeof(mob_db[0])) || mob_db[id].name[0] == '\0') return 0; @@ -79,28 +83,28 @@ int mobdb_checkid(const int id) * The minimum data set for MOB spawning *------------------------------------------ */ -int mob_spawn_dataset(struct mob_data *md,const char *mobname,int class) +int mob_spawn_dataset(struct mob_data *md,const char *mobname,int class_) { nullpo_retr(0, md); md->bl.prev=NULL; md->bl.next=NULL; if(strcmp(mobname,"--en--")==0) - memcpy(md->name,mob_db[class].name,24); + memcpy(md->name,mob_db[class_].name,24); else if(strcmp(mobname,"--ja--")==0) - memcpy(md->name,mob_db[class].jname,24); + memcpy(md->name,mob_db[class_].jname,24); else memcpy(md->name,mobname,24); md->n = 0; - md->base_class = md->class = class; + md->base_class = md->class_ = class_; md->bl.id= npc_get_new_npc_id(); memset(&md->state,0,sizeof(md->state)); md->timer = -1; md->target_id=0; md->attacked_id=0; - md->speed=mob_db[class].speed; + md->speed=mob_db[class_].speed; return 0; } @@ -110,97 +114,108 @@ int mob_spawn_dataset(struct mob_data *md,const char *mobname,int class) * The MOB appearance for one time (for scripts) *------------------------------------------ */ -int mob_once_spawn(struct map_session_data *sd,char *mapname, - int x,int y,const char *mobname,int class,int amount,const char *event) +int mob_once_spawn (struct map_session_data *sd, char *mapname, + int x, int y, const char *mobname, int class_, int amount, const char *event) { - struct mob_data *md=NULL; - int m,count,lv=255,r=class; - - if( sd ) - lv=sd->status.base_level; + struct mob_data *md = NULL; + int m, count, lv = 255; + int i, j; + + if(sd) lv = sd->status.base_level; - if( sd && strcmp(mapname,"this")==0) - m=sd->bl.m; + if(sd && strcmp(mapname,"this")==0) + m = sd->bl.m; else - m=map_mapname2mapid(mapname); + m = map_mapname2mapid(mapname); - if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>6000) // ’l‚ªˆÙí‚Ȃ碊«‚ðŽ~‚ß‚é + if (m < 0 || amount <= 0 || (class_ >= 0 && class_ <= 1000) || class_ > MAX_MOB_DB + 4000) // ’l‚ªˆÙí‚Ȃ碊«‚ðŽ~‚ß‚é return 0; - if(class<0){ // ƒ‰ƒ“ƒ_ƒ€‚ɢЫ - int i=0; - int j=-class-1; + if (class_ < 0) { // ƒ‰ƒ“ƒ_ƒ€‚ɢЫ int k; - if(j>=0 && j<MAX_RANDOMMONSTER){ - do{ - class=rand()%1000+1001; - k=rand()%1000000; - }while((mob_db[class].max_hp <= 0 || mob_db[class].summonper[j] <= k || - (lv<mob_db[class].lv && battle_config.random_monster_checklv)) && (i++) < 2000); - if(i>=2000){ - class=mob_db[0].summonper[j]; - } - }else{ + i = 0; + j = -class_-1; + if(j >= 0 && j < MAX_RANDOMMONSTER) { + do { + class_ = rand() % 1000 + 1001; + k = rand() % 1000000; + } while ((mob_db[class_].max_hp <= 0 || mob_db[class_].summonper[j] <= k || + (battle_config.random_monster_checklv && lv < mob_db[class_].lv)) && (i++) < 2000); + if(i >= 2000) + class_ = mob_db[0].summonper[j]; + } else return 0; - } // if(battle_config.etc_log) -// printf("mobclass=%d try=%d\n",class,i); +// printf("mobclass=%d try=%d\n",class_,i); } - if(sd){ - if(x<=0) x=sd->bl.x; - if(y<=0) y=sd->bl.y; - }else if(x<=0 || y<=0){ - printf("mob_once_spawn: ??\n"); + if (sd) { //even if the coords were wrong, spawn mob anyways (but look for most suitable coords first) Got from Freya [Lupus] + if (x <= 0 || y <= 0) { + if (x <= 0) x = sd->bl.x + rand() % 3 - 1; + if (y <= 0) y = sd->bl.y + rand() % 3 - 1; + if (map_getcell(m, x, y, CELL_CHKNOPASS)) { + x = sd->bl.x; + y = sd->bl.y; + } + } + } else if (x <= 0 || y <= 0) { + i = j = 0; + printf("mob_once_spawn: %i at %s x:%i y:%i\n ??\n",class_,map[m].name,x,y); //got idea from Freya [Lupus] + do { + x = rand() % (map[m].xs - 2) + 1; + y = rand() % (map[m].ys - 2) + 1; + } while ((i = map_getcell(m, x, y, CELL_CHKNOPASS)) && j++ < 64); + if (i) { // not solved? + x = 0; + y = 0; + } } - for(count=0;count<amount;count++){ - md=(struct mob_data *)aCalloc(1,sizeof(struct mob_data)); - memset(md, '\0', sizeof *md); + for (count = 0; count < amount; count++) { + md = (struct mob_data *)aCalloc(1,sizeof(struct mob_data)); + memset (md, '\0', sizeof *md); - if(class>4000) { // large/tiny mobs [Valaris] - md->size=2; - class-=4000; - } - else if(class>2000) { - md->size=1; - class-=2000; + if (class_ > MAX_MOB_DB + 2000) { // large/tiny mobs [Valaris] + md->size = 2; + class_ -= (MAX_MOB_DB + 2000); + } else if (class_ > MAX_MOB_DB) { + md->size = 1; + class_ -= MAX_MOB_DB; } - if(mob_db[class].mode&0x02) - md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item)); + if(mob_db[class_].mode & 0x02) + md->lootitem = (struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item)); else - md->lootitem=NULL; - - mob_spawn_dataset(md,mobname,class); - md->bl.m=m; - md->bl.x=x; - md->bl.y=y; - if(r<0&&battle_config.dead_branch_active) md->mode=0x1+0x4+0x80; //ˆÚ“®‚µ‚ăAƒNƒeƒBƒu‚Å”½Œ‚‚·‚é - md->m =m; - md->x0=x; - md->y0=y; - md->xs=0; - md->ys=0; - md->spawndelay1=-1; // ˆê“x‚̂݃tƒ‰ƒO - md->spawndelay2=-1; // ˆê“x‚̂݃tƒ‰ƒO + md->lootitem = NULL; - memcpy(md->npc_event,event,sizeof(md->npc_event)); - - md->bl.type=BL_MOB; - map_addiddb(&md->bl); - mob_spawn(md->bl.id); - - if(class==1288) { // emperium hp based on defense level [Valaris] - struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name); + mob_spawn_dataset (md, mobname, class_); + md->bl.m = m; + md->bl.x = x; + md->bl.y = y; + if (class_ < 0 && battle_config.dead_branch_active) + md->mode = 0x1 + 0x4 + 0x80; //ˆÚ“®‚µ‚ăAƒNƒeƒBƒu‚Å”½Œ‚‚·‚é + md->m = m; + md->x0 = x; + md->y0 = y; + //md->xs = 0; + //md->ys = 0; + md->spawndelay1 = -1; // ˆê“x‚̂݃tƒ‰ƒO + md->spawndelay2 = -1; // ˆê“x‚̂݃tƒ‰ƒO + + memcpy(md->npc_event, event, strlen(event)); + + md->bl.type = BL_MOB; + map_addiddb (&md->bl); + mob_spawn (md->bl.id); + + if(class_ == 1288) { // emperium hp based on defense level [Valaris] + struct guild_castle *gc = guild_mapname2gc(map[md->bl.m].name); if(gc) { - mob_db[class].max_hp+=2000*gc->defense; - md->hp=mob_db[class].max_hp; + mob_db[class_].max_hp += 2000 * gc->defense; + md->hp = mob_db[class_].max_hp; } } // end addition [Valaris] - - } - return (amount>0)?md->bl.id:0; + return (amount > 0) ? md->bl.id : 0; } /*========================================== * The MOB appearance for one time (& area specification for scripts) @@ -208,9 +223,9 @@ int mob_once_spawn(struct map_session_data *sd,char *mapname, */ int mob_once_spawn_area(struct map_session_data *sd,char *mapname, int x0,int y0,int x1,int y1, - const char *mobname,int class,int amount,const char *event) + const char *mobname,int class_,int amount,const char *event) { - int x,y,i,c,max,lx=-1,ly=-1,id=0; + int x,y,i,max,lx=-1,ly=-1,id=0; int m; if(strcmp(mapname,"this")==0) @@ -221,7 +236,7 @@ int mob_once_spawn_area(struct map_session_data *sd,char *mapname, max=(y1-y0+1)*(x1-x0+1)*3; if(max>1000)max=1000; - if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>6000) // A summon is stopped if a value is unusual + if(m<0 || amount<=0 || (class_>=0 && class_<=1000) || class_>MAX_MOB_DB) // A summon is stopped if a value is unusual return 0; for(i=0;i<amount;i++){ @@ -229,15 +244,17 @@ int mob_once_spawn_area(struct map_session_data *sd,char *mapname, do{ x=rand()%(x1-x0+1)+x0; y=rand()%(y1-y0+1)+y0; - }while( ( (c=map_getcell(m,x,y))==1 || c==5)&& (++j)<max ); + } while (map_getcell(m,x,y,CELL_CHKNOPASS) && (++j)<max); + // freya }while( ( (c=map_getcell(m,x,y))==1 || c==5)&& (++j)<max ); if(j>=max){ - if(lx>=0){ // ŒŸõ‚ÉŽ¸”s‚µ‚½‚̂ňȑO‚É•¦‚¢‚½êŠ‚ðŽg‚¤ + if(lx>=0){ // Since reference went wrong, the place which boiled before is used. x=lx; y=ly; }else - return 0; // ʼn‚É•¦‚ꊂ̌Ÿõ‚ðŽ¸”s‚µ‚½‚̂łâ‚ß‚é + return 0; // Since reference of the place which boils first went wrong, it stops. } - id=mob_once_spawn(sd,mapname,x,y,mobname,class,1,event); + if(x==0||y==0) printf("xory=0, x=%d,y=%d,x0=%d,y0=%d\n",x,y,x0,y0); + id=mob_once_spawn(sd,mapname,x,y,mobname,class_,1,event); lx=x; ly=y; } @@ -249,7 +266,7 @@ int mob_once_spawn_area(struct map_session_data *sd,char *mapname, *------------------------------------------ */ int mob_spawn_guardian(struct map_session_data *sd,char *mapname, - int x,int y,const char *mobname,int class,int amount,const char *event,int guardian) + int x,int y,const char *mobname,int class_,int amount,const char *event,int guardian) { struct mob_data *md=NULL; int m,count=1,lv=255; @@ -262,33 +279,27 @@ int mob_spawn_guardian(struct map_session_data *sd,char *mapname, else m=map_mapname2mapid(mapname); - if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>2000) // ’l‚ªˆÙí‚Ȃ碊«‚ðŽ~‚ß‚é + if(m<0 || amount<=0 || (class_>=0 && class_<=1000) || class_>MAX_MOB_DB) // Invalid monster classes return 0; - if(class<0) + if(class_<0) return 0; - + if(sd){ if(x<=0) x=sd->bl.x; if(y<=0) y=sd->bl.y; } - + else if(x<=0 || y<=0) printf("mob_spawn_guardian: ??\n"); - + for(count=0;count<amount;count++){ struct guild_castle *gc; - md=calloc(sizeof(struct mob_data), 1); - if(md==NULL){ - printf("mob_spawn_guardian: out of memory !\n"); - exit(1); - } + md=(struct mob_data *) aCalloc(sizeof(struct mob_data), 1); memset(md, '\0', sizeof *md); - - - mob_spawn_dataset(md,mobname,class); + mob_spawn_dataset(md,mobname,class_); md->bl.m=m; md->bl.x=x; md->bl.y=y; @@ -308,7 +319,7 @@ int mob_spawn_guardian(struct map_session_data *sd,char *mapname, gc=guild_mapname2gc(map[md->bl.m].name); if(gc) { - mob_db[class].max_hp+=2000*gc->defense; + mob_db[class_].max_hp+=2000*gc->defense; if(guardian==0) { md->hp=gc->Ghp0; gc->GID0=md->bl.id; } if(guardian==1) { md->hp=gc->Ghp1; gc->GID1=md->bl.id; } if(guardian==2) { md->hp=gc->Ghp2; gc->GID2=md->bl.id; } @@ -317,7 +328,6 @@ int mob_spawn_guardian(struct map_session_data *sd,char *mapname, if(guardian==5) { md->hp=gc->Ghp5; gc->GID5=md->bl.id; } if(guardian==6) { md->hp=gc->Ghp6; gc->GID6=md->bl.id; } if(guardian==7) { md->hp=gc->Ghp7; gc->GID7=md->bl.id; } - } } @@ -366,49 +376,49 @@ int mob_exclusion_check(struct mob_data *md,struct map_session_data *sd) * Appearance income of mob *------------------------------------------ */ -int mob_get_viewclass(int class) +int mob_get_viewclass(int class_) { - return mob_db[class].view_class; + return mob_db[class_].view_class; } -int mob_get_sex(int class) +int mob_get_sex(int class_) { - return mob_db[class].sex; + return mob_db[class_].sex; } -short mob_get_hair(int class) +short mob_get_hair(int class_) { - return mob_db[class].hair; + return mob_db[class_].hair; } -short mob_get_hair_color(int class) +short mob_get_hair_color(int class_) { - return mob_db[class].hair_color; + return mob_db[class_].hair_color; } -short mob_get_weapon(int class) +short mob_get_weapon(int class_) { - return mob_db[class].weapon; + return mob_db[class_].weapon; } -short mob_get_shield(int class) +short mob_get_shield(int class_) { - return mob_db[class].shield; + return mob_db[class_].shield; } -short mob_get_head_top(int class) +short mob_get_head_top(int class_) { - return mob_db[class].head_top; + return mob_db[class_].head_top; } -short mob_get_head_mid(int class) +short mob_get_head_mid(int class_) { - return mob_db[class].head_mid; + return mob_db[class_].head_mid; } -short mob_get_head_buttom(int class) +short mob_get_head_buttom(int class_) { - return mob_db[class].head_buttom; + return mob_db[class_].head_buttom; } -short mob_get_clothes_color(int class) // Add for player monster dye - Valaris +short mob_get_clothes_color(int class_) // Add for player monster dye - Valaris { - return mob_db[class].clothes_color; // End + return mob_db[class_].clothes_color; // End } -int mob_get_equip(int class) // mob equip [Valaris] +int mob_get_equip(int class_) // mob equip [Valaris] { - return mob_db[class].equip; + return mob_db[class_].equip; } /*========================================== * Is MOB in the state in which the present movement is possible or not? @@ -425,7 +435,7 @@ int mob_can_move(struct mob_data *md) md->sc_data[SC_AUTOCOUNTER].timer != -1 || //ƒI[ƒgƒJƒEƒ“ƒ^[ md->sc_data[SC_BLADESTOP].timer != -1 || //”’nŽæ‚è md->sc_data[SC_SPIDERWEB].timer != -1 //ƒXƒpƒCƒ_[ƒEƒFƒbƒu - ) + ) return 0; return 1; @@ -442,8 +452,8 @@ static int calc_next_walk_step(struct mob_data *md) if(md->walkpath.path_pos>=md->walkpath.path_len) return -1; if(md->walkpath.path[md->walkpath.path_pos]&1) - return battle_get_speed(&md->bl)*14/10; - return battle_get_speed(&md->bl); + return status_get_speed(&md->bl)*14/10; + return status_get_speed(&md->bl); } static int mob_walktoxy_sub(struct mob_data *md); @@ -455,7 +465,7 @@ static int mob_walktoxy_sub(struct mob_data *md); static int mob_walk(struct mob_data *md,unsigned int tick,int data) { int moveblock; - int i,ctype; + int i; static int dirx[8]={0,-1,-1,-1,0,1,1,1}; static int diry[8]={1,1,0,-1,-1,-1,0,1}; int x,y,dx,dy; @@ -480,8 +490,7 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data) x = md->bl.x; y = md->bl.y; - ctype = map_getcell(md->bl.m,x,y); - if(ctype == 1 || ctype == 5) { + if(map_getcell(md->bl.m,x,y,CELL_CHKNOPASS)) { mob_stop_walking(md,1); return 0; } @@ -489,12 +498,20 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data) dx = dirx[md->dir]; dy = diry[md->dir]; - ctype = map_getcell(md->bl.m,x+dx,y+dy); - if(ctype == 1 || ctype == 5) { + if (map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKBASILICA) && !(status_get_mode(&md->bl)&0x20)) { + mob_stop_walking(md,1); + return 0; + } + + if (map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKNOPASS)) { mob_walktoxy_sub(md); return 0; } + if (skill_check_moonlit (&md->bl,x+dx,y+dy)) { + mob_walktoxy_sub(md); + return 0; + } moveblock = ( x/BLOCK_SIZE != (x+dx)/BLOCK_SIZE || y/BLOCK_SIZE != (y+dy)/BLOCK_SIZE); md->state.state=MS_WALK; @@ -505,18 +522,18 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data) if(md->min_chase>13) md->min_chase--; + skill_unit_move(&md->bl,tick,0); if(moveblock) map_delblock(&md->bl); md->bl.x = x; md->bl.y = y; if(moveblock) map_addblock(&md->bl); + skill_unit_move(&md->bl,tick,1); map_foreachinmovearea(clif_mobinsight,md->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,-dx,-dy,BL_PC,md); md->state.state=MS_IDLE; if(md->option&4) skill_check_cloaking(&md->bl); - - skill_unit_move(&md->bl,tick,1); // ƒXƒLƒ‹ƒ†ƒjƒbƒg‚ÌŒŸ¸ } if((i=calc_next_walk_step(md))>0){ i = i>>1; @@ -591,11 +608,11 @@ static int mob_attack(struct mob_data *md,unsigned int tick,int data) if(!md->mode) - mode=mob_db[md->class].mode; + mode=mob_db[md->class_].mode; else mode=md->mode; - race=mob_db[md->class].race; + race=mob_db[md->class_].race; if(!(mode&0x80)){ md->target_id=0; md->state.targettype = NONE_ATTACKABLE; @@ -604,11 +621,11 @@ static int mob_attack(struct mob_data *md,unsigned int tick,int data) if(tsd && !(mode&0x20) && (tsd->sc_data[SC_TRICKDEAD].timer != -1 || tsd->sc_data[SC_BASILICA].timer != -1 || ((pc_ishiding(tsd) || tsd->state.gangsterparadise) && !((race == 4 || race == 6) && !tsd->perfect_hiding) ) ) ) { md->target_id=0; - md->state.targettype = NONE_ATTACKABLE; + md->state.targettype = NONE_ATTACKABLE; return 0; } - range = mob_db[md->class].range; + range = mob_db[md->class_].range; if(mode&1) range++; if(distance(md->bl.x,md->bl.y,tbl->x,tbl->y) > range) @@ -625,9 +642,9 @@ static int mob_attack(struct mob_data *md,unsigned int tick,int data) md->target_lv = battle_weapon_attack(&md->bl,tbl,tick,0); if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1) - skill_status_change_end(&md->bl,SC_CLOAKING,-1); + status_change_end(&md->bl,SC_CLOAKING,-1); - md->attackabletime = tick + battle_get_adelay(&md->bl); + md->attackabletime = tick + status_get_adelay(&md->bl); md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0); md->state.state=MS_ATTACK; @@ -684,7 +701,7 @@ int mob_changestate(struct mob_data *md,int state,int type) if(i>0 && i<2000) md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0); else if(type) { - md->attackabletime = tick + battle_get_amotion(&md->bl); + md->attackabletime = tick + status_get_amotion(&md->bl); md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0); } else { @@ -702,8 +719,8 @@ int mob_changestate(struct mob_data *md,int state,int type) md->last_deadtime=gettick(); // Since it died, all aggressors' attack to this mob is stopped. clif_foreachclient(mob_stopattacked,md->bl.id); - skill_unit_out_all(&md->bl,gettick(),1); - skill_status_change_clear(&md->bl,2); // ƒXƒe[ƒ^ƒXˆÙí‚ð‰ðœ‚·‚é + skill_unit_move(&md->bl,gettick(),0); + status_change_clear(&md->bl,2); // ƒXƒe[ƒ^ƒXˆÙí‚ð‰ðœ‚·‚é skill_clear_unitgroup(&md->bl); // ‘S‚ẴXƒLƒ‹ƒ†ƒjƒbƒgƒOƒ‹[ƒv‚ð휂·‚é skill_cleartimerskill(&md->bl); if(md->deletetimer!=-1) @@ -730,15 +747,12 @@ static int mob_timer(int tid,unsigned int tick,int id,int data) if( (bl=map_id2bl(id)) == NULL ){ //UŒ‚‚µ‚Ä‚«‚½“G‚ª‚à‚¤‚¢‚È‚¢‚̂ͳí‚̂悤‚¾ return 1; } - + if(!bl || !bl->type || bl->type!=BL_MOB) return 1; nullpo_retr(1, md=(struct mob_data*)bl); - if(!md->bl.type || md->bl.type!=BL_MOB) - return 1; - if(md->timer != tid){ if(battle_config.error_log) printf("mob_timer %d != %d\n",md->timer,tid); @@ -764,6 +778,10 @@ static int mob_timer(int tid,unsigned int tick,int id,int data) printf("mob_timer : %d ?\n",md->state.state); break; } + + if (md->timer == -1) + mob_changestate(md,MS_WALK,0); + map_freeblock_unlock(); return 0; } @@ -775,11 +793,25 @@ static int mob_timer(int tid,unsigned int tick,int id,int data) static int mob_walktoxy_sub(struct mob_data *md) { struct walkpath_data wpd; + int x,y; + static int dirx[8]={0,-1,-1,-1,0,1,1,1}; + static int diry[8]={1,1,0,-1,-1,-1,0,1}; nullpo_retr(0, md); + memset(&wpd, 0, sizeof(wpd)); + if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,md->to_x,md->to_y,md->state.walk_easy)) return 1; + if (wpd.path[0] >= 8) + return 1; + x = md->bl.x+dirx[wpd.path[0]]; + y = md->bl.y+diry[wpd.path[0]]; + if (map_getcell(md->bl.m,x,y,CELL_CHKBASILICA) && !(status_get_mode(&md->bl)&0x20)) { + md->state.change_walk_target=0; + return 1; + } + memcpy(&md->walkpath,&wpd,sizeof(wpd)); md->state.change_walk_target=0; @@ -857,7 +889,7 @@ int mob_setdelayspawn(int id) spawntime1=md->last_spawntime+md->spawndelay1; spawntime2=md->last_deadtime+md->spawndelay2; - spawntime3=gettick()+5000; + spawntime3=gettick()+5000+rand()%5000; //Lupus // spawntime = max(spawntime1,spawntime2,spawntime3); if(DIFF_TICK(spawntime1,spawntime2)>0) spawntime=spawntime1; @@ -882,7 +914,8 @@ int mob_spawn(int id) struct mob_data *md; struct block_list *bl; - nullpo_retr(-1, bl=map_id2bl(id)); + //nullpo_retr(-1, bl=map_id2bl(id)); + bl=map_id2bl(id); if(!bl || !bl->type || bl->type!=BL_MOB) return -1; @@ -891,15 +924,15 @@ int mob_spawn(int id) if(!md || !md->bl.type || md->bl.type!=BL_MOB) return -1; - + md->last_spawntime=tick; if( md->bl.prev!=NULL ){ // clif_clearchar_area(&md->bl,3); - skill_unit_out_all(&md->bl,gettick(),1); +// skill_unit_move(&md->bl,tick,0); map_delblock(&md->bl); } else - md->class = md->base_class; + md->class_ = md->base_class; md->bl.m =md->m; do { @@ -911,7 +944,7 @@ int mob_spawn(int id) y=md->y0+rand()%(md->ys+1)-md->ys/2; } i++; - } while(((c=map_getcell(md->bl.m,x,y))==1 || c==5) && i<50); + } while(map_getcell(md->bl.m,x,y,CELL_CHKNOPASS) && i<50); if(i>=50){ // if(battle_config.error_log==1) @@ -923,8 +956,7 @@ int mob_spawn(int id) md->to_x=md->bl.x=x; md->to_y=md->bl.y=y; md->dir=0; - - map_addblock(&md->bl); + md->target_dir=0; memset(&md->state,0,sizeof(md->state)); md->attacked_id = 0; @@ -932,11 +964,11 @@ int mob_spawn(int id) md->move_fail_count = 0; if(!md->speed) - md->speed = mob_db[md->class].speed; - md->def_ele = mob_db[md->class].element; + md->speed = mob_db[md->class_].speed; + md->def_ele = mob_db[md->class_].element; if(!md->level) // [Valaris] - md->level=mob_db[md->class].lv; + md->level=mob_db[md->class_].lv; md->master_id=0; md->master_dist=0; @@ -950,13 +982,12 @@ int mob_spawn(int id) md->canmove_tick = tick; md->guild_id = 0; - if (md->class >= 1285 && md->class <= 1288) { + if (md->class_ >= 1285 && md->class_ <= 1288) { struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name); if(gc) md->guild_id = gc->guild_id; } - - md->sg_count=0; + md->deletetimer=-1; md->skilltimer=-1; @@ -983,12 +1014,15 @@ int mob_spawn(int id) memset(md->skillunit,0,sizeof(md->skillunit)); memset(md->skillunittick,0,sizeof(md->skillunittick)); - md->hp = battle_get_max_hp(&md->bl); + md->hp = status_get_max_hp(&md->bl); if(md->hp<=0){ - mob_makedummymobdb(md->class); - md->hp = battle_get_max_hp(&md->bl); + mob_makedummymobdb(md->class_); + md->hp = status_get_max_hp(&md->bl); } + map_addblock(&md->bl); + skill_unit_move(&md->bl,tick,1); + clif_spawnmob(md); return 0; @@ -1026,10 +1060,9 @@ int mob_stop_walking(struct mob_data *md,int type) { nullpo_retr(0, md); - if(md->state.state == MS_WALK || md->state.state == MS_IDLE) { int dx=0,dy=0; - + md->walkpath.path_len=0; if(type&4){ dx=md->to_x-md->bl.x; @@ -1054,9 +1087,9 @@ int mob_stop_walking(struct mob_data *md,int type) if(type&0x01) clif_fixmobpos(md); if(type&0x02) { - int delay=battle_get_dmotion(&md->bl); + int delay=status_get_dmotion(&md->bl); unsigned int tick = gettick(); - if(md->canmove_tick < tick) + if(battle_config.monster_damage_delay && md->canmove_tick < tick) md->canmove_tick = tick + delay; } @@ -1079,46 +1112,43 @@ int mob_can_reach(struct mob_data *md,struct block_list *bl,int range) dx=abs(bl->x - md->bl.x); dy=abs(bl->y - md->bl.y); + if( md->bl.m != bl->m) // ˆá‚¤ƒƒbƒv + return 0; + + if( range>0 && range < ((dx>dy)?dx:dy) ) // ‰“‚·‚¬‚é + return 0; + + if( md->bl.x==bl->x && md->bl.y==bl->y ) // “¯‚¶ƒ}ƒX + return 1; + //=========== guildcastle guardian no search start=========== //when players are the guild castle member not attack them ! - if(md->class >= 1285 && md->class <= 1287){ + /*if(md->class_ >= 1285 && md->class_ <= 1287){ struct map_session_data *sd; struct guild *g=NULL; struct guild_castle *gc=guild_mapname2gc(map[bl->m].name); if(gc && agit_flag==0) // Guardians will not attack during non-woe time [Valaris] return 0; // end addition [Valaris] - - if(bl && bl->type == BL_PC){ + + if(gc && bl->type == BL_PC){ nullpo_retr(0, sd=(struct map_session_data *)bl); - if(!gc) - return 0; - if(gc && sd && sd->status.guild_id) { - g=guild_search(sd->status.guild_id); // don't attack guild members [Valaris] + if(gc && sd->status.guild_id > 0) { + g=guild_search(sd->status.guild_id); // don't attack guild members [Valaris] if(g && g->guild_id == gc->guild_id) return 0; if(g && gc && guild_isallied(g,gc)) return 0; - } } - } + }*/ //========== guildcastle guardian no search eof============== - if(bl && bl->type == BL_PC && battle_config.monsters_ignore_gm) { // option to have monsters ignore GMs [Valaris] + /*if(bl->type == BL_PC && battle_config.monsters_ignore_gm) { // option to have monsters ignore GMs [Valaris] struct map_session_data *sd; if((sd=(struct map_session_data *)bl) != NULL && pc_isGM(sd) >= battle_config.monsters_ignore_gm) return 0; - } - - if( md->bl.m != bl->m) // ˆá‚¤ƒƒbƒv - return 0; - - if( range>0 && range < ((dx>dy)?dx:dy) ) // ‰“‚·‚¬‚é - return 0; - - if( md->bl.x==bl->x && md->bl.y==bl->y ) // “¯‚¶ƒ}ƒX - return 1; + }*/ // Obstacle judging wpd.path_len=0; @@ -1156,12 +1186,12 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist) nullpo_retr(0, md); nullpo_retr(0, bl); - sc_data = battle_get_sc_data(bl); - option = battle_get_option(bl); - race=mob_db[md->class].race; + sc_data = status_get_sc_data(bl); + option = status_get_option(bl); + race=mob_db[md->class_].race; if(!md->mode) - mode=mob_db[md->class].mode; + mode=mob_db[md->class_].mode; else mode=md->mode; @@ -1170,7 +1200,9 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist) return 0; } // Nothing will be carried out if there is no mind of changing TAGE by TAGE ending. - if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && ( !(mode&0x04) || rand()%100>25) ) + if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && (!(mode&0x04) || rand()%100>25) && + // if the monster was provoked ignore the above rule [celest] + !(md->state.provoke_flag && md->state.provoke_flag == bl->id)) return 0; if(mode&0x20 || // Coercion is exerted if it is MVPMOB. @@ -1184,11 +1216,13 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist) return 0; } - md->target_id=bl->id; // Since there was no disturbance, it locks on to target. + md->target_id = bl->id; // Since there was no disturbance, it locks on to target. if(bl->type == BL_PC || bl->type == BL_MOB) md->state.targettype = ATTACKABLE; else md->state.targettype = NONE_ATTACKABLE; + if (md->state.provoke_flag) + md->state.provoke_flag = 0; md->min_chase=dist+13; if(md->min_chase>26) md->min_chase=26; @@ -1223,18 +1257,18 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) return 0; if(!smd->mode) - mode=mob_db[smd->class].mode; + mode=mob_db[smd->class_].mode; else mode=smd->mode; // ƒAƒNƒeƒBƒu‚Ń^[ƒQƒbƒgŽË’ö“à‚É‚¢‚é‚È‚çAƒƒbƒN‚·‚é if( mode&0x04 ){ - race=mob_db[smd->class].race; + race=mob_db[smd->class_].race; //‘ÎÛ‚ªPC‚Ìê‡ if(tsd && - !pc_isdead(tsd) && - tsd->bl.m == smd->bl.m && - tsd->invincible_timer == -1 && + !pc_isdead(tsd) && + tsd->bl.m == smd->bl.m && + tsd->invincible_timer == -1 && !pc_isinvisible(tsd) && (dist=distance(smd->bl.x,smd->bl.y,tsd->bl.x,tsd->bl.y))<9 ) @@ -1246,7 +1280,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) rand()%1000<1000/(++(*pcc)) ){ // ”͈͓àPC‚Å“™Šm—¦‚É‚·‚é smd->target_id=tsd->bl.id; smd->state.targettype = ATTACKABLE; - smd->min_chase=13; + smd->min_chase=13; } } } @@ -1282,10 +1316,10 @@ static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap) nullpo_retr(0, itc=va_arg(ap,int *)); if(!md->mode) - mode=mob_db[md->class].mode; + mode=mob_db[md->class_].mode; else mode=md->mode; - + if( !md->target_id && mode&0x02){ if(!md->lootitem || (battle_config.monster_loot_type == 1 && md->lootitem_count >= LOOTITEM_SIZE) ) @@ -1319,8 +1353,8 @@ static int mob_ai_sub_hard_linksearch(struct block_list *bl,va_list ap) nullpo_retr(0, target=va_arg(ap,struct block_list *)); // same family free in a range at a link monster -- it will be made to lock if MOB is -/* if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && mob_db[md->class].mode&0x08){ - if( tmd->class==md->class && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE) && tmd->bl.m == md->bl.m){ +/* if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && mob_db[md->class_].mode&0x08){ + if( tmd->class_==md->class_ && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE) && tmd->bl.m == md->bl.m){ if( mob_can_reach(tmd,target,12) ){ // Reachability judging tmd->target_id=md->target_id; tmd->state.targettype = ATTACKABLE; @@ -1328,8 +1362,8 @@ static int mob_ai_sub_hard_linksearch(struct block_list *bl,va_list ap) } } }*/ - if( md->attacked_id > 0 && mob_db[md->class].mode&0x08){ - if( tmd->class==md->class && tmd->bl.m == md->bl.m && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE)){ + if( md->attacked_id > 0 && mob_db[md->class_].mode&0x08){ + if( tmd->class_==md->class_ && tmd->bl.m == md->bl.m && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE)){ if( mob_can_reach(tmd,target,12) ){ // Reachability judging tmd->target_id=md->attacked_id; tmd->state.targettype = ATTACKABLE; @@ -1355,12 +1389,24 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) if((bl=map_id2bl(md->master_id)) != NULL ) mmd=(struct mob_data *)bl; - mode=mob_db[md->class].mode; + mode=mob_db[md->class_].mode; // It is not main monster/leader. if(!mmd || mmd->bl.type!=BL_MOB || mmd->bl.id!=md->master_id) return 0; + // ŒÄ‚Ñ–ß‚µ + if(mmd->recall_flag == 1){ + if (mmd->recallcount < (mmd->recallmob_count+2) ){ + mob_warp(md,-1,mmd->bl.x,mmd->bl.y,3); + mmd->recallcount += 1; + } else{ + mmd->recall_flag = 0; + mmd->recallcount=0; + } + md->state.master_check = 1; + return 0; + } // Since it is in the map on which the master is not, teleport is carried out and it pursues. if( mmd->bl.m != md->bl.m ){ mob_warp(md,mmd->bl.m,mmd->bl.x,mmd->bl.y,3); @@ -1380,7 +1426,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) } // Although there is the master, since it is somewhat far, it approaches. - if((!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mob_can_move(md) && + if((!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mob_can_move(md) && (md->walkpath.path_pos>=md->walkpath.path_len || md->walkpath.path_len==0) && md->master_dist<15){ int i=0,dx,dy,ret; if(md->master_dist>4) { @@ -1426,7 +1472,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) struct map_session_data *sd=map_id2sd(mmd->target_id); if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd)){ - race=mob_db[md->class].race; + race=mob_db[md->class_].race; if(mode&0x20 || (sd->sc_data[SC_TRICKDEAD].timer == -1 && sd->sc_data[SC_BASILICA].timer == -1 && ( (!pc_ishiding(sd) && !sd->state.gangsterparadise) || ((race == 4 || race == 6) && !sd->perfect_hiding) ) ) ){ // –WŠQ‚ª‚È‚¢‚©”»’è @@ -1444,7 +1490,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) struct map_session_data *sd=map_id2sd(md->target_id); if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd)){ - race=mob_db[mmd->class].race; + race=mob_db[mmd->class_].race; if(mode&0x20 || (sd->sc_data[SC_TRICKDEAD].timer == -1 && (!(sd->status.option&0x06) || race==4 || race==6) @@ -1485,23 +1531,34 @@ static int mob_randomwalk(struct mob_data *md,int tick) nullpo_retr(0, md); - speed=battle_get_speed(&md->bl); + speed=status_get_speed(&md->bl); if(DIFF_TICK(md->next_walktime,tick)<0){ int i,x,y,c,d=12-md->move_fail_count; + int mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}}; if(d<5) d=5; for(i=0;i<retrycount;i++){ // Search of a movable place int r=rand(); - x=md->bl.x+r%(d*2+1)-d; - y=md->bl.y+r/(d*2+1)%(d*2+1)-d; - if((c=map_getcell(md->bl.m,x,y))!=1 && c!=5 && mob_walktoxy(md,x,y,1)==0){ + x=r%(d*2+1)-d; + y=r/(d*2+1)%(d*2+1)-d; + if (md->target_dir){ + if (x<0) x=0-x; + if (y<0) y=0-y; + x *= mask[md->target_dir-1][0]; + y *= mask[md->target_dir-1][1]; + } + x+=md->bl.x; + y+=md->bl.y; + + if((map_getcell(md->bl.m,x,y,CELL_CHKPASS)) && mob_walktoxy(md,x,y,1)==0){ md->move_fail_count=0; break; } if(i+1>=retrycount){ md->move_fail_count++; + md->target_dir = 0; if(md->move_fail_count>1000){ if(battle_config.error_log) - printf("MOB cant move. random spawn %d, class = %d\n",md->bl.id,md->class); + printf("MOB cant move. random spawn %d, class = %d\n",md->bl.id,md->class_); md->move_fail_count=0; mob_spawn(md->bl.id); } @@ -1534,6 +1591,8 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) int i,dx,dy,ret,dist; int attack_type=0; int mode,race; + int search_size = AREA_SIZE*2; + int blind_flag = 0; nullpo_retr(0, bl); nullpo_retr(0, ap); @@ -1541,7 +1600,6 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) tick=va_arg(ap,unsigned int); - if(DIFF_TICK(tick,md->last_thinktime)<MIN_MOBTHINKTIME) return 0; md->last_thinktime=tick; @@ -1553,16 +1611,19 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) } if(!md->mode) - mode=mob_db[md->class].mode; + mode=mob_db[md->class_].mode; else mode=md->mode; - race=mob_db[md->class].race; + race=mob_db[md->class_].race; // Abnormalities if((md->opt1 > 0 && md->opt1 != 6) || md->state.state==MS_DELAY || md->sc_data[SC_BLADESTOP].timer != -1) return 0; + if (md->sc_data && md->sc_data[SC_BLIND].timer != -1) + blind_flag = 1; + if(!(mode&0x80) && md->target_id > 0) md->target_id = 0; @@ -1587,7 +1648,8 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) if(abl->type==BL_PC) asd=(struct map_session_data *)abl; if(asd==NULL || md->bl.m != abl->m || abl->prev == NULL || asd->invincible_timer != -1 || pc_isinvisible(asd) || - (dist=distance(md->bl.x,md->bl.y,abl->x,abl->y))>=32 || battle_check_target(bl,abl,BCT_ENEMY)==0) + (dist=distance(md->bl.x,md->bl.y,abl->x,abl->y))>=32 || battle_check_target(bl,abl,BCT_ENEMY)==0 || + (blind_flag && dist>3)) md->attacked_id=0; else { //‹——£‚ª‰“‚¢ê‡‚̓^ƒQ‚ð•ÏX‚µ‚È‚¢ @@ -1614,15 +1676,16 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) if( (!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mode&0x04 && !md->state.master_check && battle_config.monster_active_enable){ i=0; + search_size = (blind_flag) ? 3 : AREA_SIZE*2; if(md->state.special_mob_ai){ map_foreachinarea(mob_ai_sub_hard_activesearch,md->bl.m, - md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2, - md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2, + md->bl.x-search_size,md->bl.y-search_size, + md->bl.x+search_size,md->bl.y+search_size, 0,md,&i); }else{ map_foreachinarea(mob_ai_sub_hard_activesearch,md->bl.m, - md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2, - md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2, + md->bl.x-search_size,md->bl.y-search_size, + md->bl.x+search_size,md->bl.y+search_size, BL_PC,md,&i); } } @@ -1630,9 +1693,10 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) // The item search of a route monster if( !md->target_id && mode&0x02 && !md->state.master_check){ i=0; + search_size = (blind_flag) ? 3 : AREA_SIZE*2; map_foreachinarea(mob_ai_sub_hard_lootsearch,md->bl.m, - md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2, - md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2, + md->bl.x-search_size,md->bl.y-search_size, + md->bl.x+search_size,md->bl.y+search_size, BL_ITEM,md,&i); } @@ -1644,13 +1708,13 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) else if(tbl->type==BL_MOB) tmd=(struct mob_data *)tbl; if(tsd || tmd) { - if(tbl->m != md->bl.m || tbl->prev == NULL || (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y))>=md->min_chase) + if(tbl->m != md->bl.m || tbl->prev == NULL || (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y)) >= search_size || (blind_flag && dist>3)) mob_unlocktarget(md,tick); // •ʃ}ƒbƒv‚©AŽ‹ŠEŠO else if( tsd && !(mode&0x20) && (tsd->sc_data[SC_TRICKDEAD].timer != -1 || tsd->sc_data[SC_BASILICA].timer != -1 || ((pc_ishiding(tsd) || tsd->state.gangsterparadise) && !((race == 4 || race == 6) && !tsd->perfect_hiding) )) ) mob_unlocktarget(md,tick); // ƒXƒLƒ‹‚Ȃǂɂæ‚éô“G–WŠQ - else if(!battle_check_range(&md->bl,tbl,mob_db[md->class].range)){ + else if(!battle_check_range(&md->bl,tbl,mob_db[md->class_].range)){ // UŒ‚”͈͊O‚Ȃ̂ňړ® if(!(mode&1)){ // ˆÚ“®‚µ‚È‚¢ƒ‚[ƒh mob_unlocktarget(md,tick); @@ -1663,9 +1727,11 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) // if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tsd->bl.x,tsd->bl.y)<2) ) if(md->timer != -1 && md->state.state!=MS_ATTACK && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tbl->x,tbl->y)<2) ) return 0; // Šù‚Ɉړ®’† - if( !mob_can_reach(md,tbl,(md->min_chase>13)?md->min_chase:13) ) + search_size = (blind_flag) ? 3 : + ((md->min_chase > 13) ? md->min_chase : 13); + if(!mob_can_reach(md,tbl, search_size)) mob_unlocktarget(md,tick); // ˆÚ“®‚Å‚«‚È‚¢‚̂Ń^ƒQ‰ðœiIW‚Æ‚©Hj - else{ + else { // ’ÇÕ md->next_walktime=tick+500; i=0; @@ -1692,15 +1758,15 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) ret=mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0); i++; } while(ret && i<5); - + if(ret){ // ˆÚ“®•s‰Â”\‚ÈŠ‚©‚ç‚ÌUŒ‚‚È‚ç2•à‰º‚é if(dx<0) dx=2; else if(dx>0) dx=-2; if(dy<0) dy=2; else if(dy>0) dy=-2; mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0); + } } - } } else { // UŒ‚ŽË’ö”͈͓à md->state.skillstate=MSS_ATTACK; if(md->state.state==MS_WALK) @@ -1708,23 +1774,17 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) if(md->state.state==MS_ATTACK) return 0; // Šù‚ÉUŒ‚’† mob_changestate(md,MS_ATTACK,attack_type); - -/* if(mode&0x08){ // ƒŠƒ“ƒNƒ‚ƒ“ƒXƒ^[ - map_foreachinarea(mob_ai_sub_hard_linksearch,md->bl.m, - md->bl.x-13,md->bl.y-13, - md->bl.x+13,md->bl.y+13, - BL_MOB,md,&tsd->bl); - }*/ } return 0; - }else{ // ƒ‹[ƒgƒ‚ƒ“ƒXƒ^[ˆ— + } else { // ƒ‹[ƒgƒ‚ƒ“ƒXƒ^[ˆ— if(tbl == NULL || tbl->type != BL_ITEM ||tbl->m != md->bl.m || - (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y))>=md->min_chase || !md->lootitem){ + (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y))>=md->min_chase || !md->lootitem | + (blind_flag && dist>=4)){ // ‰“‚·‚¬‚é‚©ƒAƒCƒeƒ€‚ª‚È‚‚È‚Á‚½ mob_unlocktarget(md,tick); if(md->state.state==MS_WALK) mob_stop_walking(md,1); // •às’†‚È‚ç’âŽ~ - }else if(dist){ + } else if(dist) { if(!(mode&1)){ // ˆÚ“®‚µ‚È‚¢ƒ‚[ƒh mob_unlocktarget(md,tick); return 0; @@ -1838,7 +1898,8 @@ static int mob_ai_hard(int tid,unsigned int tick,int id,int data) */ static int mob_ai_sub_lazy(void * key,void * data,va_list app) { - struct mob_data *md=data; + struct mob_data *md=(struct mob_data *)data; + struct mob_data *mmd=NULL; unsigned int tick; va_list ap; @@ -1849,8 +1910,9 @@ static int mob_ai_sub_lazy(void * key,void * data,va_list app) if(md->bl.type!=BL_MOB) return 0; - if(!md->bl.type || md->bl.type!=BL_MOB) - return 0; + if (md->master_id > 0) { + mmd = (struct mob_data *)map_id2bl(md->master_id); //Ž©•ª‚ÌBOSS‚Ìî•ñ + } tick=va_arg(ap,unsigned int); @@ -1864,8 +1926,14 @@ static int mob_ai_sub_lazy(void * key,void * data,va_list app) return 0; } + // Žæ‚芪‚«ƒ‚ƒ“ƒXƒ^[‚̈—iŒÄ‚Ñ–ß‚µ‚³‚ê‚½Žžj + if(mmd && md->state.special_mob_ai == 0 && mmd->recall_flag == 1) { + mob_ai_sub_hard_slavemob (md,tick); + return 0; + } + if(DIFF_TICK(md->next_walktime,tick)<0 && - (mob_db[md->class].mode&1) && mob_can_move(md) ){ + (mob_db[md->class_].mode&1) && mob_can_move(md) ){ if( map[md->bl.m].users>0 ){ // Since PC is in the same map, somewhat better negligent processing is carried out. @@ -1876,7 +1944,7 @@ static int mob_ai_sub_lazy(void * key,void * data,va_list app) // MOB which is not not the summons MOB but BOSS, either sometimes reboils. else if( rand()%1000<MOB_LAZYWARPPERC && md->x0<=0 && md->master_id!=0 && - mob_db[md->class].mexp <= 0 && !(mob_db[md->class].mode & 0x20)) + mob_db[md->class_].mexp <= 0 && !(mob_db[md->class_].mode & 0x20)) mob_spawn(md->bl.id); }else{ @@ -1884,7 +1952,7 @@ static int mob_ai_sub_lazy(void * key,void * data,va_list app) // MOB which is not BOSS which is not Summons MOB, either -- a case -- sometimes -- leaping if( rand()%1000<MOB_LAZYWARPPERC && md->x0<=0 && md->master_id!=0 && - mob_db[md->class].mexp <= 0 && !(mob_db[md->class].mode & 0x20)) + mob_db[md->class_].mexp <= 0 && !(mob_db[md->class_].mode & 0x20)) mob_warp(md,-1,-1,-1,-1); } @@ -1931,7 +1999,7 @@ static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data) { struct delay_item_drop *ditem; struct item temp_item; - int flag; + int flag, drop_flag = 1; nullpo_retr(0, ditem=(struct delay_item_drop *)id); @@ -1940,18 +2008,45 @@ static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data) temp_item.amount = ditem->amount; temp_item.identify = !itemdb_isequip3(temp_item.nameid); - if(battle_config.item_auto_get){ - if(ditem->first_sd && (flag = pc_additem(ditem->first_sd,&temp_item,ditem->amount))){ - clif_additem(ditem->first_sd,0,0,flag); - map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0); + if (ditem->first_sd){ + #if 0 + if (ditem->first_sd->status.party_id > 0){ + struct party *p; + if((p=party_search(ditem->first_sd->status.party_id)) && p->item){ + struct map_session_data *sd = NULL; + int i; + for (i = p->itemc + 1; i!=p->itemc; i++) { // initialise counter and loop through the party + if (i >= MAX_PARTY) + i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc" + if ((sd=p->member[i].sd)!=NULL && sd->bl.m == ditem->first_sd->bl.m) + break; + } + if (sd){ // if an appropiate party member was found + drop_flag = 0; + if ((p->itemc++) >= MAX_PARTY) + p->itemc = 0; + if ((flag = pc_additem(ditem->first_sd,&temp_item,ditem->amount))) { + clif_additem(ditem->first_sd,0,0,flag); + drop_flag = 1; + } + } + } + } else + #endif + if(battle_config.item_auto_get || ditem->first_sd->autoloot){//Autoloot added by Upa-Kun + drop_flag = 0; + if((flag = pc_additem(ditem->first_sd,&temp_item,ditem->amount))){ + clif_additem(ditem->first_sd,0,0,flag); + drop_flag = 1; + } } - free(ditem); - return 0; } - map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0); + if (drop_flag) { + map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0); + } - free(ditem); + aFree(ditem); return 0; } @@ -1962,22 +2057,49 @@ static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data) static int mob_delay_item_drop2(int tid,unsigned int tick,int id,int data) { struct delay_item_drop2 *ditem; - int flag; + int flag, drop_flag = 1; nullpo_retr(0, ditem=(struct delay_item_drop2 *)id); - if(battle_config.item_auto_get){ - if(ditem->first_sd && (flag = pc_additem(ditem->first_sd,&ditem->item_data,ditem->item_data.amount))){ - clif_additem(ditem->first_sd,0,0,flag); - map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0); + if (ditem->first_sd){ + #if 0 + if (ditem->first_sd->status.party_id > 0){ + struct party *p; + if((p=party_search(ditem->first_sd->status.party_id)) && p->item){ + struct map_session_data *sd = NULL; + int i; + for (i = p->itemc + 1; i!=p->itemc; i++) { // initialise counter and loop through the party + if (i >= MAX_PARTY) + i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc" + if ((sd=p->member[i].sd)!=NULL && sd->bl.m == ditem->first_sd->bl.m) + break; + } + if (sd){ // if an appropiate party member was found + drop_flag = 0; + if ((p->itemc++) >= MAX_PARTY) + p->itemc = 0; + if((flag = pc_additem(ditem->first_sd,&ditem->item_data,ditem->item_data.amount))){ + clif_additem(ditem->first_sd,0,0,flag); + drop_flag = 1; + } + } + } + } else + #endif + if(battle_config.item_auto_get || ditem->first_sd->autoloot){//Autoloot added by Upa-Kun + drop_flag = 0; + if((flag = pc_additem(ditem->first_sd,&ditem->item_data,ditem->item_data.amount))){ + clif_additem(ditem->first_sd,0,0,flag); + drop_flag = 1; + } } - free(ditem); - return 0; } - map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0); + if (drop_flag) { + map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0); + } - free(ditem); + aFree(ditem); return 0; } @@ -1985,44 +2107,49 @@ static int mob_delay_item_drop2(int tid,unsigned int tick,int id,int data) * mob data is erased. *------------------------------------------ */ -int mob_delete(struct mob_data *md) +void mob_unload(struct mob_data *md) +{ + nullpo_retv(md); + mob_remove_map(md, 0); + map_deliddb(&md->bl); + aFree(md); + md = NULL; +} +int mob_remove_map(struct mob_data *md, int type) { nullpo_retr(1, md); if(md->bl.prev == NULL) return 1; mob_changestate(md,MS_DEAD,0); - clif_clearchar_area(&md->bl,1); + clif_clearchar_area(&md->bl,type); map_delblock(&md->bl); - if(mob_get_viewclass(md->class) <= 1000) - clif_clearchar_delay(gettick()+3000,&md->bl,0); - mob_deleteslave(md); - mob_setdelayspawn(md->bl.id); + if (md->lootitem){ + aFree(md->lootitem); + md->lootitem = NULL; + } + return 0; } - -int mob_catch_delete(struct mob_data *md,int type) +int mob_delete(struct mob_data *md) { nullpo_retr(1, md); - if(md->bl.prev == NULL) - return 1; - mob_changestate(md,MS_DEAD,0); - clif_clearchar_area(&md->bl,type); - map_delblock(&md->bl); + mob_remove_map(md, 1); + if (mob_get_viewclass(md->class_) <= 1000) + clif_clearchar_delay(gettick()+3000,&md->bl,0); + mob_deleteslave(md); mob_setdelayspawn(md->bl.id); return 0; } - int mob_timer_delete(int tid, unsigned int tick, int id, int data) { - struct block_list *bl=map_id2bl(id); - struct mob_data *md; - - nullpo_retr(0, bl); + struct mob_data *md=(struct mob_data *)map_id2bl(id); + nullpo_retr(0, md); - md = (struct mob_data *)bl; - mob_catch_delete(md,3); +//for Alchemist CANNIBALIZE [Lupus] + mob_remove_map(md, 3); + mob_setdelayspawn(md->bl.id); return 0; } @@ -2074,15 +2201,17 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) int mvp_damage,max_hp; unsigned int tick = gettick(); struct map_session_data *mvp_sd = NULL, *second_sd = NULL,*third_sd = NULL; - double dmg_rate,tdmg,temp; + struct block_list *master = NULL; + double tdmg,temp; struct item item; int ret; int drop_rate; - int skill,sp; - + int race; + nullpo_retr(0, md); //src‚ÍNULL‚ŌĂ΂ê‚éê‡‚à‚ ‚é‚Ì‚ÅA‘¼‚Ń`ƒFƒbƒN - max_hp = battle_get_max_hp(&md->bl); + max_hp = status_get_max_hp(&md->bl); + race = status_get_race(&md->bl); if(src && src->type == BL_PC) { sd = (struct map_session_data *)src; @@ -2108,7 +2237,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) return 0; } - if(md->sc_data[SC_ENDURE].timer == -1) + if(battle_config.monster_damage_delay && md->sc_data[SC_ENDURE].timer == -1) mob_stop_walking(md,3); if(damage > max_hp>>2) skill_stop_dancing(&md->bl,0); @@ -2123,7 +2252,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) if(!(type&2)) { if(sd!=NULL){ for(i=0,minpos=0,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){ - if(md->dmglog[i].id==sd->bl.id) + //if(md->dmglog[i].id==sd->bl.id) + if(md->dmglog[i].id==sd->status.char_id) break; if(md->dmglog[i].id==0){ minpos=i; @@ -2137,7 +2267,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) if(i<DAMAGELOG_SIZE) md->dmglog[i].dmg+=damage; else { - md->dmglog[minpos].id=sd->bl.id; + //md->dmglog[minpos].id=sd->bl.id; + md->dmglog[minpos].id=sd->status.char_id; md->dmglog[minpos].dmg=damage; } @@ -2148,7 +2279,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) struct pet_data *pd = (struct pet_data *)src; nullpo_retr(0, pd); for(i=0,minpos=0,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){ - if(md->dmglog[i].id==pd->msd->bl.id) + //if(md->dmglog[i].id==pd->msd->bl.id) + if(md->dmglog[i].id==pd->msd->status.char_id) break; if(md->dmglog[i].id==0){ minpos=i; @@ -2162,7 +2294,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) if(i<DAMAGELOG_SIZE) md->dmglog[i].dmg+=(damage*battle_config.pet_attack_exp_rate)/100; else { - md->dmglog[minpos].id=pd->msd->bl.id; + //md->dmglog[minpos].id=pd->msd->bl.id; + md->dmglog[minpos].id=pd->msd->status.char_id; md->dmglog[minpos].dmg=(damage*battle_config.pet_attack_exp_rate)/100; } } @@ -2195,88 +2328,92 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) } md->hp-=damage; - - if(md->class >= 1285 && md->class <=1287) { // guardian hp update [Valaris] + + if(md->class_ >= 1285 && md->class_ <=1287) { // guardian hp update [Valaris] struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name); if(gc) { - if(md->bl.id==gc->GID0) { + if(md->bl.id==gc->GID0) { gc->Ghp0=md->hp; if(gc->Ghp0<=0) { guild_castledatasave(gc->castle_id,10,0); guild_castledatasave(gc->castle_id,18,0); } - } - if(md->bl.id==gc->GID1) { + } + if(md->bl.id==gc->GID1) { gc->Ghp1=md->hp; if(gc->Ghp1<=0) { guild_castledatasave(gc->castle_id,11,0); guild_castledatasave(gc->castle_id,19,0); } } - if(md->bl.id==gc->GID2) { + if(md->bl.id==gc->GID2) { gc->Ghp2=md->hp; if(gc->Ghp2<=0) { guild_castledatasave(gc->castle_id,12,0); guild_castledatasave(gc->castle_id,20,0); } } - if(md->bl.id==gc->GID3) { + if(md->bl.id==gc->GID3) { gc->Ghp3=md->hp; if(gc->Ghp3<=0) { guild_castledatasave(gc->castle_id,13,0); guild_castledatasave(gc->castle_id,21,0); } } - if(md->bl.id==gc->GID4) { + if(md->bl.id==gc->GID4) { gc->Ghp4=md->hp; if(gc->Ghp4<=0) { guild_castledatasave(gc->castle_id,14,0); guild_castledatasave(gc->castle_id,22,0); } } - if(md->bl.id==gc->GID5) { + if(md->bl.id==gc->GID5) { gc->Ghp5=md->hp; if(gc->Ghp5<=0) { guild_castledatasave(gc->castle_id,15,0); guild_castledatasave(gc->castle_id,23,0); } } - if(md->bl.id==gc->GID6) { + if(md->bl.id==gc->GID6) { gc->Ghp6=md->hp; if(gc->Ghp6<=0) { guild_castledatasave(gc->castle_id,16,0); guild_castledatasave(gc->castle_id,24,0); } } - if(md->bl.id==gc->GID7) { + if(md->bl.id==gc->GID7) { gc->Ghp7=md->hp; if(gc->Ghp7<=0) { guild_castledatasave(gc->castle_id,17,0); guild_castledatasave(gc->castle_id,25,0); - + } } } } // end addition [Valaris] - + if(md->option&2 ) - skill_status_change_end(&md->bl, SC_HIDING, -1); + status_change_end(&md->bl, SC_HIDING, -1); if(md->option&4 ) - skill_status_change_end(&md->bl, SC_CLOAKING, -1); + status_change_end(&md->bl, SC_CLOAKING, -1); if(md->state.special_mob_ai == 2){//ƒXƒtƒBƒA[ƒ}ƒCƒ“ int skillidx=0; - - if((skillidx=mob_skillid2skillidx(md->class,NPC_SELFDESTRUCTION2))>=0){ + + if((skillidx=mob_skillid2skillidx(md->class_,NPC_SELFDESTRUCTION2))>=0){ md->mode |= 0x1; md->next_walktime=tick; mobskill_use_id(md,&md->bl,skillidx);//Ž©”š‰r¥ŠJŽn md->state.special_mob_ai++; } + if (src && md->master_id==src->id) + md->target_dir=map_calc_dir(src,md->bl.x,md->bl.y)+1; } if(md->hp>0){ + if (battle_config.show_mob_hp) + clif_update_mobhp (md); return 0; } @@ -2289,19 +2426,33 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) memset(tmpsd,0,sizeof(tmpsd)); memset(pt,0,sizeof(pt)); - max_hp = battle_get_max_hp(&md->bl); + max_hp = status_get_max_hp(&md->bl); if(src && src->type == BL_MOB) mob_unlocktarget((struct mob_data *)src,tick); - /* ƒ\ƒEƒ‹ƒhƒŒƒCƒ“ */ - if(sd && (skill=pc_checkskill(sd,HW_SOULDRAIN))>0){ - clif_skill_nodamage(src,&md->bl,HW_SOULDRAIN,skill,1); - sp = (battle_get_lv(&md->bl))*(65+15*skill)/100; - if(sd->status.sp + sp > sd->status.max_sp) - sp = sd->status.max_sp - sd->status.sp; - sd->status.sp += sp; - clif_heal(sd->fd,SP_SP,sp); + + if(sd) { + int sp = 0, hp = 0; + if (sd->state.attack_type == BF_MAGIC && (i=pc_checkskill(sd,HW_SOULDRAIN))>0){ /* ƒ\ƒEƒ‹ƒhƒŒƒCƒ“ */ + clif_skill_nodamage(src,&md->bl,HW_SOULDRAIN,i,1); + sp += (status_get_lv(&md->bl))*(65+15*i)/100; + } + sp += sd->sp_gain_value; + sp += sd->sp_gain_race[race]; + hp += sd->hp_gain_value; + if (sp > 0) { + if(sd->status.sp + sp > sd->status.max_sp) + sp = sd->status.max_sp - sd->status.sp; + sd->status.sp += sp; + clif_heal(sd->fd,SP_SP,sp); + } + if (hp > 0) { + if(sd->status.hp + hp > sd->status.max_hp) + hp = sd->status.max_hp - sd->status.hp; + sd->status.hp += hp; + clif_heal(sd->fd,SP_HP,hp); + } } // mapŠO‚ÉÁ‚¦‚½l‚ÍŒvŽZ‚©‚眂‚̂Š@@ -2311,7 +2462,12 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) for(i=0,count=0,mvp_damage=0;i<DAMAGELOG_SIZE;i++){ if(md->dmglog[i].id==0) continue; - tmpsd[i] = map_id2sd(md->dmglog[i].id); + // Will this slow things down too much? + tmpsd[i] = map_charid2sd(md->dmglog[i].id); + // try finding again + if(tmpsd[i] == NULL) + tmpsd[i] = map_id2sd(md->dmglog[i].id); + // if we still can't find the player if(tmpsd[i] == NULL) continue; count++; @@ -2327,64 +2483,81 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) } } - // [MouseJstr] - if((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1)) { - - if((double)max_hp < tdmg) - dmg_rate = ((double)max_hp) / tdmg; - else dmg_rate = 1; + // [MouseJstr] + if((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1)) { // ŒoŒ±’l‚Ì•ª”z for(i=0;i<DAMAGELOG_SIZE;i++){ int pid,base_exp,job_exp,flag=1,zeny=0; double per; struct party *p; - if(tmpsd[i]==NULL || tmpsd[i]->bl.m != md->bl.m) + if(tmpsd[i]==NULL || tmpsd[i]->bl.m != md->bl.m || pc_isdead(tmpsd[i])) continue; -/* jAthena's exp formula - per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./((double)max_hp) * dmg_rate; - temp = ((double)mob_db[md->class].base_exp * (double)battle_config.base_exp_rate / 100. * per); - base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp; - if(mob_db[md->class].base_exp > 0 && base_exp < 1) base_exp = 1; - if(base_exp < 0) base_exp = 0; - temp = ((double)mob_db[md->class].job_exp * (double)battle_config.job_exp_rate / 100. * per); - job_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp; - if(mob_db[md->class].job_exp > 0 && job_exp < 1) job_exp = 1; - if(job_exp < 0) job_exp = 0; -*/ -//eAthena's exp formula rather than jAthena's - per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/(double)max_hp; - if(per>512) per=512; - if(per<1) per=1; - base_exp=mob_db[md->class].base_exp*per/256; - - if(base_exp < 1) base_exp = 1; - if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class].lv - sd->status.base_level >= 20)) { - base_exp*=1.15; // pk_mode additional exp if monster >20 levels [Valaris] - } - job_exp=mob_db[md->class].job_exp*per/256; - if(job_exp < 1) job_exp = 1; - if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class].lv - sd->status.base_level >= 20)) { - job_exp*=1.15; // pk_mode additional exp if monster >20 levels [Valaris] + + if (battle_config.exp_calc_type == 0) { + // jAthena's exp formula + per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./tdmg; + temp = (double)mob_db[md->class_].base_exp * per; + base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp; + if(mob_db[md->class_].base_exp > 0 && base_exp < 1) base_exp = 1; + if(base_exp < 0) base_exp = 0; + temp = (double)mob_db[md->class_].job_exp * per; + job_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp; + if(mob_db[md->class_].job_exp > 0 && job_exp < 1) job_exp = 1; + if(job_exp < 0) job_exp = 0; } - if(md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) { // for summoned creatures [Valaris] - base_exp = 0; - job_exp = 0; + else if (battle_config.exp_calc_type == 1) { + //eAthena's exp formula rather than jAthena's + per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/(double)max_hp; + if(per>512) per=512; + if(per<1) per=1; + base_exp=(int) (mob_db[md->class_].base_exp*per/256); + if(base_exp < 1) base_exp = 1; + job_exp=(int) (mob_db[md->class_].job_exp*per/256); + if(job_exp < 1) job_exp = 1; } else { - if(battle_config.zeny_from_mobs) { - if(md->level > 0) zeny=(md->level+rand()%md->level)*per/256; // zeny calculation moblv + random moblv [Valaris] - if(mob_db[md->class].mexp > 0) + //eAthena's exp formula rather than jAthena's, but based on total damage dealt + per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/tdmg; + if(per>512) per=512; + if(per<1) per=1; + base_exp=(int) (mob_db[md->class_].base_exp*per/256); + if(base_exp < 1) base_exp = 1; + job_exp=(int) (mob_db[md->class_].job_exp*per/256); + if(job_exp < 1) job_exp = 1; + } + + if(sd) { + int rate; + if ((rate = sd->expaddrace[race]) > 0) { + base_exp = (100+rate)*base_exp/100; + job_exp = (100+rate)*job_exp/100; + } + if (battle_config.pk_mode && (mob_db[md->class_].lv - sd->status.base_level >= 20)) { + base_exp = (int) (base_exp *1.15); // pk_mode additional exp if monster >20 levels [Valaris] + job_exp = (int) (job_exp * 1.15); + } + } + if(md->master_id) { + if(((master = map_id2bl(md->master_id)) && status_get_mode(master)&0x20) || // check if its master is a boss (MVP's and minibosses) + (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1)) { // for summoned creatures [Valaris] + base_exp = 0; + job_exp = 0; + } + } else { + if(battle_config.zeny_from_mobs) { + if(md->level > 0) zeny=(int) ((md->level+rand()%md->level)*per/256); // zeny calculation moblv + random moblv [Valaris] + if(mob_db[md->class_].mexp > 0) zeny*=rand()%250; } - if(battle_config.mobs_level_up && md->level > mob_db[md->class].lv) { // [Valaris] - job_exp+=((md->level-mob_db[md->class].lv)*mob_db[md->class].job_exp*.03)*per/256; - base_exp+=((md->level-mob_db[md->class].lv)*mob_db[md->class].base_exp*.03)*per/256; + if(battle_config.mobs_level_up && md->level > mob_db[md->class_].lv) { // [Valaris] + job_exp+=(int) (((md->level-mob_db[md->class_].lv)*mob_db[md->class_].job_exp*.03)*per/256); + base_exp+=(int) (((md->level-mob_db[md->class_].lv)*mob_db[md->class_].base_exp*.03)*per/256); } } - + if((pid=tmpsd[i]->status.party_id)>0){ // ƒp[ƒeƒB‚É“ü‚Á‚Ä‚¢‚é - int j=0; + int j; for(j=0;j<pnum;j++) // Œö•½ƒp[ƒeƒBƒŠƒXƒg‚É‚¢‚é‚©‚Ç‚¤‚© if(pt[j].id==pid) break; @@ -2422,26 +2595,31 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) // item drop if(!(type&1)) { - int log_item[8] = {0}; - for(i=0;i<8;i++){ + int log_item[10] = {0}; //8 -> 10 Lupus + int drop_ore = -1,drop_items=0; //slot N for DROP LOG, number of dropped items + for(i=0;i<10;i++){ // 8 -> 10 Lupus struct delay_item_drop *ditem; int drop_rate; - if(md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) // Added [Valaris] + if((master && status_get_mode(master)&0x20) || // check if its master is a boss (MVP's and minibosses) + (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1)) // Added [Valaris] break; // End - if(mob_db[md->class].dropitem[i].nameid <= 0) + if(mob_db[md->class_].dropitem[i].nameid <= 0) continue; - drop_rate = mob_db[md->class].dropitem[i].p; - if(drop_rate <= 0 && battle_config.drop_rate0item) + drop_rate = mob_db[md->class_].dropitem[i].p; + if(drop_rate <= 0 && !battle_config.drop_rate0item) drop_rate = 1; if(battle_config.drops_by_luk>0 && sd && md) drop_rate+=(sd->status.luk*battle_config.drops_by_luk)/100; // drops affected by luk [Valaris] - if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class].lv - sd->status.base_level >= 20)) drop_rate*=1.25; // pk_mode increase drops if 20 level difference [Valaris] - if(drop_rate <= rand()%10000) + if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class_].lv - sd->status.base_level >= 20)) drop_rate = (int) (drop_rate*1.25); // pk_mode increase drops if 20 level difference [Valaris] + if(drop_rate < rand() % 10000 + 1) { //fixed 0.01% impossible drops bug [Lupus] + drop_ore = i; //we remember an empty slot to put there ORE DISCOVERY drop later. continue; + } + drop_items++; //we count if there were any drops ditem=(struct delay_item_drop *)aCalloc(1,sizeof(struct delay_item_drop)); - ditem->nameid = mob_db[md->class].dropitem[i].nameid; + ditem->nameid = mob_db[md->class_].dropitem[i].nameid; log_item[i] = ditem->nameid; ditem->amount = 1; ditem->m = md->bl.m; @@ -2453,18 +2631,14 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) add_timer(tick+500+i,mob_delay_item_drop,(int)ditem,0); } - #ifndef TXT_ONLY - if(log_config.drop > 0) - log_drop(mvp_sd, md->class, log_item); - #endif - // Ore Discovery [Celest] - if (pc_checkskill(sd,BS_FINDINGORE)>0 && 1 >= rand()%1000) { + if (sd == mvp_sd && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/100 >= rand()%1000) { struct delay_item_drop *ditem; - int itemid[17] = { 714, 756, 757, 969, 984, 985, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1002 }; ditem=(struct delay_item_drop *)aCalloc(1,sizeof(struct delay_item_drop)); - ditem->nameid = itemid[rand()%17]; - log_item[i] = ditem->nameid; + ditem->nameid = itemdb_searchrandomid(6); + if (drop_ore<0) i=8; //we have only 10 slots in LOG, there's a check to not overflow (9th item usually a card, so we use 8th slot) + log_item[i] = ditem->nameid; //it's for logging only + drop_items++; //we count if there were any drops ditem->amount = 1; ditem->m = md->bl.m; ditem->x = md->bl.x; @@ -2475,20 +2649,18 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) add_timer(tick+500+i,mob_delay_item_drop,(int)ditem,0); } - #ifndef TXT_ONLY - if(log_config.drop > 0) - log_drop(mvp_sd, md->class, log_item); - #endif + //this drop log contains ALL dropped items + ORE (if there was ORE Recovery) [Lupus] + if(sd && log_config.drop > 0 && drop_items) //we check were there any drops.. and if not - don't write the log + log_drop(sd, md->class_, log_item); //mvp_sd if(sd && sd->state.attack_type == BF_WEAPON) { for(i=0;i<sd->monster_drop_item_count;i++) { struct delay_item_drop *ditem; - int race = battle_get_race(&md->bl); if(sd->monster_drop_itemid[i] <= 0) continue; - if(sd->monster_drop_race[i] & (1<<race) || - (mob_db[md->class].mode & 0x20 && sd->monster_drop_race[i] & 1<<10) || - (!(mob_db[md->class].mode & 0x20) && sd->monster_drop_race[i] & 1<<11) ) { + if(sd->monster_drop_race[i] & (1<<race) || + (mob_db[md->class_].mode & 0x20 && sd->monster_drop_race[i] & 1<<10) || + (!(mob_db[md->class_].mode & 0x20) && sd->monster_drop_race[i] & 1<<11) ) { if(sd->monster_drop_itemrate[i] <= rand()%10000) continue; @@ -2505,7 +2677,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) } } if(sd->get_zeny_num > 0) - pc_getzeny(sd,mob_db[md->class].lv*10 + rand()%(sd->get_zeny_num+1)); + pc_getzeny(sd,mob_db[md->class_].lv*10 + rand()%(sd->get_zeny_num+1)); } if(md->lootitem) { for(i=0;i<md->lootitem_count;i++) { @@ -2525,11 +2697,11 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) } // mvpˆ— - if(mvp_sd && mob_db[md->class].mexp > 0 ){ + if(mvp_sd && mob_db[md->class_].mexp > 0 ){ int log_mvp[2] = {0}; int j; int mexp; - temp = ((double)mob_db[md->class].mexp * (double)battle_config.mvp_exp_rate * (9.+(double)count)/1000.); + temp = ((double)mob_db[md->class_].mexp * (9.+(double)count)/10.); //[Gengar] mexp = (temp > 2147483647.)? 0x7fffffff:(int)temp; if(mexp < 1) mexp = 1; clif_mvp_effect(mvp_sd); // ƒGƒtƒFƒNƒg @@ -2538,19 +2710,20 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) log_mvp[1] = mexp; for(j=0;j<3;j++){ i = rand() % 3; - if(mob_db[md->class].mvpitem[i].nameid <= 0) + if(mob_db[md->class_].mvpitem[i].nameid <= 0) continue; - drop_rate = mob_db[md->class].mvpitem[i].p; - if(drop_rate <= 0 && battle_config.drop_rate0item) + drop_rate = mob_db[md->class_].mvpitem[i].p; + if(drop_rate <= 0 && !battle_config.drop_rate0item) drop_rate = 1; - if(drop_rate < battle_config.item_drop_mvp_min) +/* if(drop_rate < battle_config.item_drop_mvp_min) drop_rate = battle_config.item_drop_mvp_min; - if(drop_rate > battle_config.item_drop_mvp_max) + else if(drop_rate > battle_config.item_drop_mvp_max) //fixed drop_rate = battle_config.item_drop_mvp_max; - if(drop_rate <= rand()%10000) +*/ + if(drop_rate <= rand()%10000+1) //if ==0, then it doesn't drop continue; memset(&item,0,sizeof(item)); - item.nameid=mob_db[md->class].mvpitem[i].nameid; + item.nameid=mob_db[md->class_].mvpitem[i].nameid; item.identify=!itemdb_isequip3(item.nameid); clif_mvp_item(mvp_sd,item.nameid); log_mvp[0] = item.nameid; @@ -2562,10 +2735,9 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) } break; } - #ifndef TXT_ONLY - if(log_config.mvpdrop > 0) - log_mvpdrop(mvp_sd, md->class, log_mvp); - #endif + + if(log_config.mvpdrop > 0) + log_mvpdrop(mvp_sd, md->class_, log_mvp); } } // [MouseJstr] @@ -2574,7 +2746,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) if(md->npc_event[0] && strcmp(((md->npc_event)+strlen(md->npc_event)-13),"::OnAgitBreak") == 0) { printf("MOB.C: Run NPC_Event[OnAgitBreak].\n"); if (agit_flag == 1) //Call to Run NPC_Event[OnAgitBreak] - guild_agit_break(md); + guild_agit_break(md); } // SCRIPTŽÀs @@ -2590,7 +2762,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) struct map_session_data *tmpsd; int i; for(i=0;i<fd_max;i++){ - if(session[i] && (tmpsd=session[i]->session_data) && tmpsd->state.auth) { + if(session[i] && (tmpsd= (struct map_session_data *) session[i]->session_data) && tmpsd->state.auth) { if(md->bl.m == tmpsd->bl.m) { sd = tmpsd; break; @@ -2606,7 +2778,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) clif_clearchar_area(&md->bl,1); if(md->level) md->level=0; map_delblock(&md->bl); - if(mob_get_viewclass(md->class) <= 1000) + if(mob_get_viewclass(md->class_) <= 1000) clif_clearchar_delay(tick+3000,&md->bl,0); mob_deleteslave(md); mob_setdelayspawn(md->bl.id); @@ -2622,26 +2794,26 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) int mob_class_change(struct mob_data *md,int *value) { unsigned int tick = gettick(); - int i,c,hp_rate,max_hp,class,count = 0; + int i,c,hp_rate,max_hp,class_,count = 0; nullpo_retr(0, md); nullpo_retr(0, value); - if(value[0]<=1000 || value[0]>2000) + if(value[0]<=1000 || value[0]>MAX_MOB_DB) return 0; if(md->bl.prev == NULL) return 0; - while(count < 5 && value[count] > 1000 && value[count] <= 2000) count++; + while(count < 5 && value[count] > 1000 && value[count] <= MAX_MOB_DB) count++; if(count < 1) return 0; - class = value[rand()%count]; - if(class<=1000 || class>2000) return 0; + class_ = value[rand()%count]; + if(class_<=1000 || class_>MAX_MOB_DB) return 0; - max_hp = battle_get_max_hp(&md->bl); + max_hp = status_get_max_hp(&md->bl); hp_rate = md->hp*100/max_hp; - clif_mob_class_change(md,class); - md->class = class; - max_hp = battle_get_max_hp(&md->bl); + clif_mob_class_change(md,class_); + md->class_ = class_; + max_hp = status_get_max_hp(&md->bl); if(battle_config.monster_class_change_full_recover==1) { md->hp = max_hp; memset(md->dmglog,0,sizeof(md->dmglog)); @@ -2651,14 +2823,14 @@ int mob_class_change(struct mob_data *md,int *value) if(md->hp > max_hp) md->hp = max_hp; else if(md->hp < 1) md->hp = 1; - memcpy(md->name,mob_db[class].jname,24); + memcpy(md->name,mob_db[class_].jname,24); memset(&md->state,0,sizeof(md->state)); md->attacked_id = 0; md->target_id = 0; md->move_fail_count = 0; - md->speed = mob_db[md->class].speed; - md->def_ele = mob_db[md->class].element; + md->speed = mob_db[md->class_].speed; + md->def_ele = mob_db[md->class_].element; mob_changestate(md,MS_IDLE,0); skill_castcancel(&md->bl,0); @@ -2667,14 +2839,13 @@ int mob_class_change(struct mob_data *md,int *value) md->next_walktime = tick+rand()%50+5000; md->attackabletime = tick; md->canmove_tick = tick; - md->sg_count=0; for(i=0,c=tick-1000*3600*10;i<MAX_MOBSKILL;i++) md->skilldelay[i] = c; md->skillid=0; md->skilllv=0; - if(md->lootitem == NULL && mob_db[class].mode&0x02) + if(md->lootitem == NULL && mob_db[class_].mode&0x02) md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item)); skill_clear_unitgroup(&md->bl); @@ -2692,15 +2863,16 @@ int mob_class_change(struct mob_data *md,int *value) */ int mob_heal(struct mob_data *md,int heal) { - int max_hp = battle_get_max_hp(&md->bl); + int max_hp; nullpo_retr(0, md); + max_hp = status_get_max_hp(&md->bl); md->hp += heal; if( max_hp < md->hp ) md->hp = max_hp; - if(md->class >= 1285 && md->class <=1287) { // guardian hp update [Valaris] + if(md->class_ >= 1285 && md->class_ <=1287) { // guardian hp update [Valaris] struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name); if(gc) { if(md->bl.id==gc->GID0) gc->Ghp0=md->hp; @@ -2714,6 +2886,9 @@ int mob_heal(struct mob_data *md,int heal) } } // end addition [Valaris] + if (battle_config.show_mob_hp) + clif_update_mobhp(md); + return 0; } @@ -2755,7 +2930,8 @@ int mob_warpslave(struct mob_data *md,int x, int y) */ int mob_warp(struct mob_data *md,int m,int x,int y,int type) { - int i=0,c,xs=0,ys=0,bx=x,by=y; + int i=0,xs=0,ys=0,bx=x,by=y; + int tick = gettick(); nullpo_retr(0, md); @@ -2769,14 +2945,14 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type) return 0; clif_clearchar_area(&md->bl,type); } - skill_unit_out_all(&md->bl,gettick(),1); + skill_unit_move(&md->bl,tick,0); map_delblock(&md->bl); if(bx>0 && by>0){ // ˆÊ’uŽw’è‚ÌꇎüˆÍ‚XƒZƒ‹‚ð’Tõ xs=ys=9; } - while( ( x<0 || y<0 || ((c=read_gat(m,x,y))==1 || c==5) ) && (i++)<1000 ){ + while( ( x<0 || y<0 || map_getcell(m,x,y,CELL_CHKNOPASS)) && (i++)<1000 ){ if( xs>0 && ys>0 && i<250 ){ // Žw’èˆÊ’u•t‹ß‚Ì’Tõ x=bx+rand()%xs-xs/2; y=by+rand()%ys-ys/2; @@ -2793,7 +2969,7 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type) }else { m=md->bl.m; if(battle_config.error_log==1) - printf("MOB %d warp failed, class = %d\n",md->bl.id,md->class); + printf("MOB %d warp failed, class = %d\n",md->bl.id,md->class_); } md->target_id=0; // ƒ^ƒQ‚ð‰ðœ‚·‚é @@ -2804,10 +2980,11 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type) if(type>0 && i==1000) { if(battle_config.battle_log) - printf("MOB %d warp to (%d,%d), class = %d\n",md->bl.id,x,y,md->class); + printf("MOB %d warp to (%d,%d), class = %d\n",md->bl.id,x,y,md->class_); } map_addblock(&md->bl); + skill_unit_move(&md->bl,tick,1); if(type>0) { clif_spawnmob(md); @@ -2833,7 +3010,6 @@ int mob_countslave_sub(struct block_list *bl,va_list ap) nullpo_retr(0, c=va_arg(ap,int *)); nullpo_retr(0, md = (struct mob_data *)bl); - if( md->master_id==id ) (*c)++; return 0; @@ -2860,7 +3036,7 @@ int mob_countslave(struct mob_data *md) int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag) { struct mob_data *md; - int bx,by,m,count = 0,class,k,a = amount; + int bx,by,m,count = 0,class_,k,a = amount; nullpo_retr(0, md2); nullpo_retr(0, value); @@ -2869,24 +3045,24 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag) by=md2->bl.y; m=md2->bl.m; - if(value[0]<=1000 || value[0]>2000) // ’l‚ªˆÙí‚Ȃ碊«‚ðŽ~‚ß‚é + if(value[0]<=1000 || value[0]>MAX_MOB_DB) // ’l‚ªˆÙí‚Ȃ碊«‚ðŽ~‚ß‚é return 0; - while(count < 5 && value[count] > 1000 && value[count] <= 2000) count++; + while(count < 21 && value[count] > 1000 && value[count] <= 2000) count++; if(count < 1) return 0; for(k=0;k<count;k++) { amount = a; - class = value[k]; - if(class<=1000 || class>2000) continue; + class_ = value[k]; + if(class_<=1000 || class_>MAX_MOB_DB) continue; for(;amount>0;amount--){ - int x=0,y=0,c=0,i=0; + int x=0,y=0,i=0; md=(struct mob_data *)aCalloc(1,sizeof(struct mob_data)); - if(mob_db[class].mode&0x02) + if(mob_db[class_].mode&0x02) md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item)); else md->lootitem=NULL; - while((x<=0 || y<=0 || (c=map_getcell(m,x,y))==1 || c==5 ) && (i++)<100){ + while((x<=0 || y<=0 || map_getcell(m,x,y,CELL_CHKNOPASS)) && (i++)<100){ x=rand()%9-4+bx; y=rand()%9-4+by; } @@ -2895,7 +3071,7 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag) y=by; } - mob_spawn_dataset(md,"--ja--",class); + mob_spawn_dataset(md,"--ja--",class_); md->bl.m=m; md->bl.x=x; md->bl.y=y; @@ -2976,15 +3152,15 @@ int mob_counttargeted(struct mob_data *md,struct block_list *src,int target_lv) *MOBskill‚©‚çŠY“–skillid‚Ìskillidx‚ð•Ô‚· *------------------------------------------ */ -int mob_skillid2skillidx(int class,int skillid) +int mob_skillid2skillidx(int class_,int skillid) { int i; - struct mob_skill *ms=mob_db[class].skill; - + struct mob_skill *ms=mob_db[class_].skill; + if(ms==NULL) return -1; - for(i=0;i<mob_db[class].maxskill;i++){ + for(i=0;i<mob_db[class_].maxskill;i++){ if(ms[i].skill_id == skillid) return i; } @@ -3023,7 +3199,9 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data ) md->skilltimer=-1; //’¾–Ù‚âó‘ÔˆÙí‚È‚Ç if(md->sc_data){ - if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1) + if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || + (!(mob_db[md->class_].mode & 0x20) && md->sc_data[SC_ROKISWEIL].timer != -1) || + md->sc_data[SC_STEELBODY].timer != -1) return 0; if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //ƒI[ƒgƒJƒEƒ“ƒ^[ return 0; @@ -3033,7 +3211,7 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data ) return 0; } if(md->skillid != NPC_EMOTION) - md->last_thinktime=tick + battle_get_adelay(&md->bl); + md->last_thinktime=tick + status_get_adelay(&md->bl); if((bl = map_id2bl(md->skilltarget)) == NULL || bl->prev==NULL){ //ƒXƒLƒ‹ƒ^[ƒQƒbƒg‚ª‘¶Ý‚µ‚È‚¢ //printf("mobskill_castend_id nullpo\n");//ƒ^[ƒQƒbƒg‚ª‚¢‚È‚¢‚Æ‚«‚Ínullpo‚¶‚á‚È‚‚Ä•’Ê‚ÉI—¹ @@ -3043,12 +3221,12 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data ) return 0; if(md->skillid == PR_LEXAETERNA) { - struct status_change *sc_data = battle_get_sc_data(bl); + struct status_change *sc_data = status_get_sc_data(bl); if(sc_data && (sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0))) return 0; } else if(md->skillid == RG_BACKSTAP) { - int dir = map_calc_dir(&md->bl,bl->x,bl->y),t_dir = battle_get_dir(bl); + int dir = map_calc_dir(&md->bl,bl->x,bl->y),t_dir = status_get_dir(bl); int dist = distance(md->bl.x,md->bl.y,bl->x,bl->y); if(bl->type != BL_SKILL && (dist == 0 || map_check_dir(dir,t_dir))) return 0; @@ -3058,14 +3236,14 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data ) return 0; range = skill_get_range(md->skillid,md->skilllv); if(range < 0) - range = battle_get_range(&md->bl) - (range + 1); + range = status_get_range(&md->bl) - (range + 1); if(range + battle_config.mob_skill_add_range < distance(md->bl.x,md->bl.y,bl->x,bl->y)) return 0; md->skilldelay[md->skillidx]=tick; if(battle_config.mob_skill_log) - printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class); + printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class_); // mob_stop_walking(md,0); switch( skill_get_nk(md->skillid) ) @@ -3075,8 +3253,8 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data ) skill_castend_damage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0); break; case 1:// Žx‰‡Œn - if(!mob_db[md->class].skill[md->skillidx].val[0] && - (md->skillid==AL_HEAL || (md->skillid==ALL_RESURRECTION && bl->type != BL_PC)) && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) ) + if(!mob_db[md->class_].skill[md->skillidx].val[0] && + (md->skillid==AL_HEAL || (md->skillid==ALL_RESURRECTION && bl->type != BL_PC)) && battle_check_undead(status_get_race(bl),status_get_elem_type(bl)) ) skill_castend_damage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0); else skill_castend_nodamage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0); @@ -3094,15 +3272,10 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data ) int mobskill_castend_pos( int tid, unsigned int tick, int id,int data ) { struct mob_data* md=NULL; - struct block_list *bl; int range,maxcount; - //mobskill_castend_id“¯—l‰r¥‚µ‚½Mob‚ª‰r¥Š®—¹Žž‚É‚à‚¤‚¢‚È‚¢‚Æ‚¢‚¤‚̂͂ ‚è‚»‚¤‚Ȃ̂Ånullpo‚©‚眊O - if((bl=map_id2bl(id))==NULL) - return 0; + nullpo_retr(0, md=(struct mob_data *)map_id2bl(id)); - nullpo_retr(0, md=(struct mob_data *)bl); - if( md->bl.type!=BL_MOB || md->bl.prev==NULL ) return 0; @@ -3111,7 +3284,9 @@ int mobskill_castend_pos( int tid, unsigned int tick, int id,int data ) md->skilltimer=-1; if(md->sc_data){ - if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1) + if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || + (!(mob_db[md->class_].mode & 0x20) && md->sc_data[SC_ROKISWEIL].timer != -1) || + md->sc_data[SC_STEELBODY].timer != -1) return 0; if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //ƒI[ƒgƒJƒEƒ“ƒ^[ return 0; @@ -3121,59 +3296,16 @@ int mobskill_castend_pos( int tid, unsigned int tick, int id,int data ) return 0; } - if(battle_config.monster_skill_reiteration == 0) { - range = -1; - switch(md->skillid) { - case MG_SAFETYWALL: - case WZ_FIREPILLAR: - case HT_SKIDTRAP: - case HT_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case PF_SPIDERWEB: /* ƒXƒpƒCƒ_[ƒEƒFƒbƒu */ - range = 0; - break; - case AL_PNEUMA: - case AL_WARP: - range = 1; - break; - } - if(range >= 0) { - if(skill_check_unit_range(md->bl.m,md->skillx,md->skilly,range,md->skillid) > 0) - return 0; - } - } - if(battle_config.monster_skill_nofootset) { - range = -1; - switch(md->skillid) { - case WZ_FIREPILLAR: - case HT_SKIDTRAP: - case HT_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case AM_DEMONSTRATION: - case PF_SPIDERWEB: /* ƒXƒpƒCƒ_[ƒEƒFƒbƒu */ - range = 1; - break; - case AL_WARP: - range = 0; - break; - } - if(range >= 0) { - if(skill_check_unit_range2(md->bl.m,md->skillx,md->skilly,range) > 0) - return 0; - } - } + if (!battle_config.monster_skill_reiteration && + skill_get_unit_flag (md->skillid) & UF_NOREITERATION && + skill_check_unit_range (md->bl.m, md->skillx, md->skilly, md->skillid, md->skilllv)) + return 0; + + if(battle_config.monster_skill_nofootset && + skill_get_unit_flag (md->skillid) & UF_NOFOOTSET && + skill_check_unit_range2(&md->bl, md->bl.m, md->skillx, md->skilly, md->skillid, md->skilllv)) + return 0; + if(battle_config.monster_land_skill_limit) { maxcount = skill_get_maxcount(md->skillid); @@ -3190,13 +3322,13 @@ int mobskill_castend_pos( int tid, unsigned int tick, int id,int data ) range = skill_get_range(md->skillid,md->skilllv); if(range < 0) - range = battle_get_range(&md->bl) - (range + 1); + range = status_get_range(&md->bl) - (range + 1); if(range + battle_config.mob_skill_add_range < distance(md->bl.x,md->bl.y,md->skillx,md->skilly)) return 0; md->skilldelay[md->skillidx]=tick; if(battle_config.mob_skill_log) - printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class); + printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class_); // mob_stop_walking(md,0); skill_castend_pos2(&md->bl,md->skillx,md->skilly,md->skillid,md->skilllv,tick,0); @@ -3216,8 +3348,8 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx) int skill_id, skill_lv, forcecast = 0; nullpo_retr(0, md); - nullpo_retr(0, ms=&mob_db[md->class].skill[skill_idx]); - + nullpo_retr(0, ms=&mob_db[md->class_].skill[skill_idx]); + if( target==NULL && (target=map_id2bl(md->target_id))==NULL ) return 0; @@ -3229,7 +3361,9 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx) // ’¾–Ù‚âˆÙí if(md->sc_data){ - if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1) + if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || + (!(mob_db[md->class_].mode & 0x20) && md->sc_data[SC_ROKISWEIL].timer != -1) || + md->sc_data[SC_STEELBODY].timer != -1) return 0; if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //ƒI[ƒgƒJƒEƒ“ƒ^[ return 0; @@ -3244,17 +3378,15 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx) if(md->option&2 && skill_id!=TF_HIDING && skill_id!=AS_GRIMTOOTH && skill_id!=RG_BACKSTAP && skill_id!=RG_RAID) return 0; - if(map[md->bl.m].flag.gvg && (skill_id == SM_ENDURE || skill_id == AL_TELEPORT || skill_id == AL_WARP || - skill_id == WZ_ICEWALL || skill_id == TF_BACKSLIDING)) + if(map[md->bl.m].flag.gvg && skill_db[skill_id].nocast & 4) return 0; - if(skill_get_inf2(skill_id)&0x200 && md->bl.id == target->id) return 0; // ŽË’ö‚ÆáŠQ•¨ƒ`ƒFƒbƒN range = skill_get_range(skill_id,skill_lv); if(range < 0) - range = battle_get_range(&md->bl) - (range + 1); + range = status_get_range(&md->bl) - (range + 1); if(!battle_check_range(&md->bl,target,range)) return 0; @@ -3266,7 +3398,7 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx) switch(skill_id){ /* ‰½‚©“ÁŽê‚Ȉ—‚ª•K—v */ case ALL_RESURRECTION: /* ƒŠƒUƒŒƒNƒVƒ‡ƒ“ */ - if(target->type != BL_PC && battle_check_undead(battle_get_race(target),battle_get_elem_type(target))){ /* “G‚ªƒAƒ“ƒfƒbƒh‚È‚ç */ + if(target->type != BL_PC && battle_check_undead(status_get_race(target),status_get_elem_type(target))){ /* “G‚ªƒAƒ“ƒfƒbƒh‚È‚ç */ forcecast=1; /* ƒ^[ƒ“ƒAƒ“ƒfƒbƒg‚Æ“¯‚¶‰r¥ŽžŠÔ */ casttime=skill_castfix(&md->bl, skill_get_cast(PR_TURNUNDEAD,skill_lv) ); } @@ -3276,10 +3408,15 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx) case SA_SPELLBREAKER: forcecast=1; break; + case NPC_SUMMONSLAVE: + case NPC_SUMMONMONSTER: + if(md->master_id!=0) + return 0; + break; } if(battle_config.mob_skill_log) - printf("MOB skill use target_id=%d skill=%d lv=%d cast=%d, class = %d\n",target->id,skill_id,skill_lv,casttime,md->class); + printf("MOB skill use target_id=%d skill=%d lv=%d cast=%d, class = %d\n",target->id,skill_id,skill_lv,casttime,md->class_); if(casttime>0 || forcecast){ // ‰r¥‚ª•K—v // struct mob_data *md2; @@ -3288,8 +3425,9 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx) md->bl.id, target->id, 0,0, skill_id,casttime); // ‰r¥”½‰žƒ‚ƒ“ƒXƒ^[ -/* if( target->type==BL_MOB && mob_db[(md2=(struct mob_data *)target)->class].mode&0x10 && - md2->state.state!=MS_ATTACK){ + // future homunculus support? +/* if(md->master_id && target->type==BL_MOB && (md2=(struct mob_data *)target) && + mob_db[md2->class_].mode&0x10 && md2->state.state!=MS_ATTACK){ md2->target_id=md->bl.id; md->state.targettype = ATTACKABLE; md2->min_chase=13; @@ -3307,7 +3445,7 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx) md->skillidx = skill_idx; if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1 && md->skillid != AS_CLOAKING) - skill_status_change_end(&md->bl,SC_CLOAKING,-1); + status_change_end(&md->bl,SC_CLOAKING,-1); if( casttime>0 ){ md->skilltimer = @@ -3332,7 +3470,7 @@ int mobskill_use_pos( struct mob_data *md, int skill_id, skill_lv; nullpo_retr(0, md); - nullpo_retr(0, ms=&mob_db[md->class].skill[skill_idx]); + nullpo_retr(0, ms=&mob_db[md->class_].skill[skill_idx]); if( md->bl.prev==NULL ) return 0; @@ -3342,7 +3480,9 @@ int mobskill_use_pos( struct mob_data *md, //’¾–Ù‚âó‘ÔˆÙí‚È‚Ç if(md->sc_data){ - if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1) + if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || + (!(mob_db[md->class_].mode & 0x20) && md->sc_data[SC_ROKISWEIL].timer != -1) || + md->sc_data[SC_STEELBODY].timer != -1) return 0; if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //ƒI[ƒgƒJƒEƒ“ƒ^[ return 0; @@ -3366,7 +3506,7 @@ int mobskill_use_pos( struct mob_data *md, bl.y = skill_y; range = skill_get_range(skill_id,skill_lv); if(range < 0) - range = battle_get_range(&md->bl) - (range + 1); + range = status_get_range(&md->bl) - (range + 1); if(!battle_check_range(&md->bl,&bl,range)) return 0; @@ -3377,7 +3517,7 @@ int mobskill_use_pos( struct mob_data *md, if(battle_config.mob_skill_log) printf("MOB skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d, class = %d\n", - skill_x,skill_y,skill_id,skill_lv,casttime,md->class); + skill_x,skill_y,skill_id,skill_lv,casttime,md->class_); if( casttime>0 ) { // A cast time is required. mob_stop_walking(md,0); // •às’âŽ~ @@ -3396,7 +3536,7 @@ int mobskill_use_pos( struct mob_data *md, md->skilllv = skill_lv; md->skillidx = skill_idx; if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1) - skill_status_change_end(&md->bl,SC_CLOAKING,-1); + status_change_end(&md->bl,SC_CLOAKING,-1); if( casttime>0 ){ md->skilltimer = add_timer( gettick()+casttime, mobskill_castend_pos, md->bl.id, 0 ); @@ -3428,7 +3568,7 @@ int mob_getfriendhpltmaxrate_sub(struct block_list *bl,va_list ap) return 0; rate=va_arg(ap,int); fr=va_arg(ap,struct mob_data **); - if( md->hp < mob_db[md->class].max_hp*rate/100 ) + if( md->hp < mob_db[md->class_].max_hp*rate/100 ) (*fr)=md; return 0; } @@ -3500,9 +3640,9 @@ int mobskill_use(struct mob_data *md,unsigned int tick,int event) int i,max_hp; nullpo_retr(0, md); - nullpo_retr(0, ms = mob_db[md->class].skill); + nullpo_retr(0, ms = mob_db[md->class_].skill); - max_hp = battle_get_max_hp(&md->bl); + max_hp = status_get_max_hp(&md->bl); if(battle_config.mob_skill_use == 0 || md->skilltimer != -1) return 0; @@ -3513,7 +3653,7 @@ int mobskill_use(struct mob_data *md,unsigned int tick,int event) if(md->sc_data[SC_SELFDESTRUCTION].timer!=-1) //Ž©”š’†‚ÍƒXƒLƒ‹‚ðŽg‚í‚È‚¢ return 0; - for(i=0;i<mob_db[md->class].maxskill;i++){ + for(i=0;i<mob_db[md->class_].maxskill;i++){ int c2=ms[i].cond2,flag=0; struct mob_data *fmd=NULL; @@ -3579,24 +3719,24 @@ int mobskill_use(struct mob_data *md,unsigned int tick,int event) continue; // Ž©•ª‚ÌŽüˆÍ if( ms[i].target>=MST_AROUND1 ){ - int bx=x, by=y, i=0, c, m=bl->m, r=ms[i].target-MST_AROUND1; + int bx=x, by=y, i=0, m=bl->m, r=ms[i].target-MST_AROUND1; do{ bx=x + rand()%(r*2+3) - r; by=y + rand()%(r*2+3) - r; }while( ( bx<=0 || by<=0 || bx>=map[m].xs || by>=map[m].ys || - ((c=read_gat(m,bx,by))==1 || c==5) ) && (i++)<1000); + map_getcell(m,bx,by,CELL_CHKNOPASS)) && (i++)<1000); if(i<1000){ x=bx; y=by; } } // ‘ŠŽè‚ÌŽüˆÍ if( ms[i].target>=MST_AROUND5 ){ - int bx=x, by=y, i=0, c, m=bl->m, r=(ms[i].target-MST_AROUND5)+1; + int bx=x, by=y, i=0,m=bl->m, r=(ms[i].target-MST_AROUND5)+1; do{ bx=x + rand()%(r*2+1) - r; by=y + rand()%(r*2+1) - r; }while( ( bx<=0 || by<=0 || bx>=map[m].xs || by>=map[m].ys || - ((c=read_gat(m,bx,by))==1 || c==5) ) && (i++)<1000); + map_getcell(m,bx,by,CELL_CHKNOPASS)) && (i++)<1000); if(i<1000){ x=bx; y=by; } @@ -3645,27 +3785,30 @@ int mobskill_event(struct mob_data *md,int flag) int mob_gvmobcheck(struct map_session_data *sd, struct block_list *bl) { struct mob_data *md=NULL; - + nullpo_retr(0,sd); nullpo_retr(0,bl); - + if(bl->type==BL_MOB && (md=(struct mob_data *)bl) && - (md->class == 1288 || md->class == 1287 || md->class == 1286 || md->class == 1285)) + (md->class_ == 1288 || md->class_ == 1287 || md->class_ == 1286 || md->class_ == 1285)) { struct guild_castle *gc=guild_mapname2gc(map[sd->bl.m].name); struct guild *g=guild_search(sd->status.guild_id); - if(g == NULL && md->class == 1288) + if(g == NULL && md->class_ == 1288) return 0;//ƒMƒ‹ƒh–¢‰Á“ü‚È‚çƒ_ƒ[ƒW–³‚µ else if(gc != NULL && !map[sd->bl.m].flag.gvg) return 0;//Ô“à‚ÅGv‚¶‚á‚È‚¢‚Æ‚«‚̓_ƒ[ƒW‚È‚µ - else if(g && gc != NULL && g->guild_id == gc->guild_id) - return 0;//Ž©è—̃Mƒ‹ƒh‚̃Gƒ“ƒy‚È‚çƒ_ƒ[ƒW–³‚µ - else if(g && guild_checkskill(g,GD_APPROVAL) <= 0 && md->class == 1288) - return 0;//³‹KƒMƒ‹ƒh³”F‚ª‚È‚¢‚ƃ_ƒ[ƒW–³‚µ - + else if(g) { + if (gc != NULL && g->guild_id == gc->guild_id) + return 0;//Ž©è—̃Mƒ‹ƒh‚̃Gƒ“ƒy‚È‚çƒ_ƒ[ƒW–³‚µ + else if(guild_checkskill(g,GD_APPROVAL) <= 0 && md->class_ == 1288) + return 0;//³‹KƒMƒ‹ƒh³”F‚ª‚È‚¢‚ƃ_ƒ[ƒW–³‚µ + else if (gc && guild_check_alliance(gc->guild_id, g->guild_id, 0) == 1) + return 0; // “¯–¿‚È‚çƒ_ƒ[ƒW–³‚µ + } } - + return 1; } /*========================================== @@ -3692,53 +3835,53 @@ int mobskill_deltimer(struct mob_data *md ) * Since un-setting [ mob ] up was used, it is an initial provisional value setup. *------------------------------------------ */ -static int mob_makedummymobdb(int class) +static int mob_makedummymobdb(int class_) { int i; - sprintf(mob_db[class].name,"mob%d",class); - sprintf(mob_db[class].jname,"mob%d",class); - mob_db[class].lv=1; - mob_db[class].max_hp=1000; - mob_db[class].max_sp=1; - mob_db[class].base_exp=2; - mob_db[class].job_exp=1; - mob_db[class].range=1; - mob_db[class].atk1=7; - mob_db[class].atk2=10; - mob_db[class].def=0; - mob_db[class].mdef=0; - mob_db[class].str=1; - mob_db[class].agi=1; - mob_db[class].vit=1; - mob_db[class].int_=1; - mob_db[class].dex=6; - mob_db[class].luk=2; - mob_db[class].range2=10; - mob_db[class].range3=10; - mob_db[class].size=0; - mob_db[class].race=0; - mob_db[class].element=0; - mob_db[class].mode=0; - mob_db[class].speed=300; - mob_db[class].adelay=1000; - mob_db[class].amotion=500; - mob_db[class].dmotion=500; - mob_db[class].dropitem[0].nameid=909; // Jellopy - mob_db[class].dropitem[0].p=1000; - for(i=1;i<8;i++){ - mob_db[class].dropitem[i].nameid=0; - mob_db[class].dropitem[i].p=0; + sprintf(mob_db[class_].name,"mob%d",class_); + sprintf(mob_db[class_].jname,"mob%d",class_); + mob_db[class_].lv=1; + mob_db[class_].max_hp=1000; + mob_db[class_].max_sp=1; + mob_db[class_].base_exp=2; + mob_db[class_].job_exp=1; + mob_db[class_].range=1; + mob_db[class_].atk1=7; + mob_db[class_].atk2=10; + mob_db[class_].def=0; + mob_db[class_].mdef=0; + mob_db[class_].str=1; + mob_db[class_].agi=1; + mob_db[class_].vit=1; + mob_db[class_].int_=1; + mob_db[class_].dex=6; + mob_db[class_].luk=2; + mob_db[class_].range2=10; + mob_db[class_].range3=10; + mob_db[class_].size=0; + mob_db[class_].race=0; + mob_db[class_].element=0; + mob_db[class_].mode=0; + mob_db[class_].speed=300; + mob_db[class_].adelay=1000; + mob_db[class_].amotion=500; + mob_db[class_].dmotion=500; + //mob_db[class_].dropitem[0].nameid=909; // Jellopy + //mob_db[class_].dropitem[0].p=1000; + for(i=1;i<10;i++){ // 8-> 10 Lupus + mob_db[class_].dropitem[i].nameid=0; + mob_db[class_].dropitem[i].p=0; } // Item1,Item2 - mob_db[class].mexp=0; - mob_db[class].mexpper=0; + mob_db[class_].mexp=0; + mob_db[class_].mexpper=0; for(i=0;i<3;i++){ - mob_db[class].mvpitem[i].nameid=0; - mob_db[class].mvpitem[i].p=0; + mob_db[class_].mvpitem[i].nameid=0; + mob_db[class_].mvpitem[i].p=0; } for(i=0;i<MAX_RANDOMMONSTER;i++) - mob_db[class].summonper[i]=0; + mob_db[class_].summonper[i]=0; return 0; } @@ -3764,13 +3907,13 @@ static int mob_readdb(void) return -1; } while(fgets(line,1020,fp)){ - int class,i; - char *str[55],*p,*np; + int class_,i; + char *str[60],*p,*np; // 55->60 Lupus if(line[0] == '/' && line[1] == '/') continue; - for(i=0,p=line;i<55;i++){ + for(i=0,p=line;i<60;i++){ if((np=strchr(p,','))!=NULL){ str[i]=p; *np=0; @@ -3779,113 +3922,122 @@ static int mob_readdb(void) str[i]=p; } - class=atoi(str[0]); - if(class<=1000 || class>2000) + class_=atoi(str[0]); + if(class_<=1000 || class_>MAX_MOB_DB) continue; - mob_db[class].view_class=class; - memcpy(mob_db[class].name,str[1],24); - memcpy(mob_db[class].jname,str[2],24); - mob_db[class].lv=atoi(str[3]); - mob_db[class].max_hp=atoi(str[4]); - mob_db[class].max_sp=atoi(str[5]); - - mob_db[class].base_exp=atoi(str[6]); - if(mob_db[class].base_exp < 0) - mob_db[class].base_exp = 0; - else if(mob_db[class].base_exp > 0 && (mob_db[class].base_exp*battle_config.base_exp_rate/100 > 1000000000 || - mob_db[class].base_exp*battle_config.base_exp_rate/100 < 0)) - mob_db[class].base_exp=1000000000; - else - mob_db[class].base_exp*= battle_config.base_exp_rate/100; - - mob_db[class].job_exp=atoi(str[7]); - if(mob_db[class].job_exp < 0) - mob_db[class].job_exp = 0; - else if(mob_db[class].job_exp > 0 && (mob_db[class].job_exp*battle_config.job_exp_rate/100 > 1000000000 || - mob_db[class].job_exp*battle_config.job_exp_rate/100 < 0)) - mob_db[class].job_exp=1000000000; - else - mob_db[class].job_exp*=battle_config.job_exp_rate/100; - - mob_db[class].range=atoi(str[8]); - mob_db[class].atk1=atoi(str[9]); - mob_db[class].atk2=atoi(str[10]); - mob_db[class].def=atoi(str[11]); - mob_db[class].mdef=atoi(str[12]); - mob_db[class].str=atoi(str[13]); - mob_db[class].agi=atoi(str[14]); - mob_db[class].vit=atoi(str[15]); - mob_db[class].int_=atoi(str[16]); - mob_db[class].dex=atoi(str[17]); - mob_db[class].luk=atoi(str[18]); - mob_db[class].range2=atoi(str[19]); - mob_db[class].range3=atoi(str[20]); - mob_db[class].size=atoi(str[21]); - mob_db[class].race=atoi(str[22]); - mob_db[class].element=atoi(str[23]); - mob_db[class].mode=atoi(str[24]); - mob_db[class].speed=atoi(str[25]); - mob_db[class].adelay=atoi(str[26]); - mob_db[class].amotion=atoi(str[27]); - mob_db[class].dmotion=atoi(str[28]); - - for(i=0;i<8;i++){ + mob_db[class_].view_class=class_; + memcpy(mob_db[class_].name,str[1],24); + memcpy(mob_db[class_].jname,str[2],24); + mob_db[class_].lv=atoi(str[3]); + mob_db[class_].max_hp=atoi(str[4]); + mob_db[class_].max_sp=atoi(str[5]); + + mob_db[class_].base_exp = atoi(str[6]); + if (mob_db[class_].base_exp <= 0) + mob_db[class_].base_exp = 0; + else if (mob_db[class_].base_exp * battle_config.base_exp_rate / 100 > 1000000000 || + mob_db[class_].base_exp * battle_config.base_exp_rate / 100 < 0) + mob_db[class_].base_exp = 1000000000; + else { + mob_db[class_].base_exp = mob_db[class_].base_exp * battle_config.base_exp_rate / 100; + if (mob_db[class_].base_exp < 1) + mob_db[class_].base_exp = 1; + } + + mob_db[class_].job_exp = atoi(str[7]); + if (mob_db[class_].job_exp <= 0) + mob_db[class_].job_exp = 0; + else if (mob_db[class_].job_exp * battle_config.job_exp_rate / 100 > 1000000000 || + mob_db[class_].job_exp * battle_config.job_exp_rate / 100 < 0) + mob_db[class_].job_exp = 1000000000; + else { + mob_db[class_].job_exp = mob_db[class_].job_exp * battle_config.job_exp_rate / 100; + if (mob_db[class_].job_exp < 1) + mob_db[class_].job_exp = 1; + } + + mob_db[class_].range=atoi(str[8]); + mob_db[class_].atk1=atoi(str[9]); + mob_db[class_].atk2=atoi(str[10]); + mob_db[class_].def=atoi(str[11]); + mob_db[class_].mdef=atoi(str[12]); + mob_db[class_].str=atoi(str[13]); + mob_db[class_].agi=atoi(str[14]); + mob_db[class_].vit=atoi(str[15]); + mob_db[class_].int_=atoi(str[16]); + mob_db[class_].dex=atoi(str[17]); + mob_db[class_].luk=atoi(str[18]); + mob_db[class_].range2=atoi(str[19]); + mob_db[class_].range3=atoi(str[20]); + mob_db[class_].size=atoi(str[21]); + mob_db[class_].race=atoi(str[22]); + mob_db[class_].element=atoi(str[23]); + mob_db[class_].mode=atoi(str[24]); + mob_db[class_].speed=atoi(str[25]); + mob_db[class_].adelay=atoi(str[26]); + mob_db[class_].amotion=atoi(str[27]); + mob_db[class_].dmotion=atoi(str[28]); + + for(i=0;i<10;i++){ // 8 -> 10 Lupus int rate = 0,type,ratemin,ratemax; - mob_db[class].dropitem[i].nameid=atoi(str[29+i*2]); - type = itemdb_type(mob_db[class].dropitem[i].nameid); - if (type == 0) { // Added [Valaris] - rate = battle_config.item_rate_heal; + mob_db[class_].dropitem[i].nameid=atoi(str[29+i*2]); + type = itemdb_type(mob_db[class_].dropitem[i].nameid); + if (type == 0) { + rate = battle_config.item_rate_heal * atoi(str[30+i*2]) / 100; //fix by Yor ratemin = battle_config.item_drop_heal_min; ratemax = battle_config.item_drop_heal_max; } else if (type == 2) { - rate = battle_config.item_rate_use; + rate = battle_config.item_rate_use * atoi(str[30+i*2]) / 100; //fix by Yor ratemin = battle_config.item_drop_use_min; ratemax = battle_config.item_drop_use_max; // End } else if (type == 4 || type == 5 || type == 8) { // Changed to include Pet Equip - rate = battle_config.item_rate_equip; + rate = battle_config.item_rate_equip * atoi(str[30+i*2]) / 100; ratemin = battle_config.item_drop_equip_min; ratemax = battle_config.item_drop_equip_max; } else if (type == 6) { - rate = battle_config.item_rate_card; + rate = battle_config.item_rate_card * atoi(str[30+i*2]) / 100; ratemin = battle_config.item_drop_card_min; ratemax = battle_config.item_drop_card_max; } else { - rate = battle_config.item_rate_common; + rate = battle_config.item_rate_common * atoi(str[30+i*2]) / 100; ratemin = battle_config.item_drop_common_min; ratemax = battle_config.item_drop_common_max; } - rate = (rate / 100) * atoi(str[30+i*2]); - rate = (rate < ratemin)? ratemin: (rate > ratemax)? ratemax: rate; - mob_db[class].dropitem[i].p = rate; + mob_db[class_].dropitem[i].p = (rate < ratemin) ? ratemin : (rate > ratemax) ? ratemax: rate; } - // Item1,Item2 - mob_db[class].mexp=atoi(str[45])*battle_config.mvp_exp_rate/100; - mob_db[class].mexpper=atoi(str[46]); + // MVP EXP Bonus, Chance: MEXP,ExpPer + mob_db[class_].mexp=atoi(str[49])*battle_config.mvp_exp_rate/100; + mob_db[class_].mexpper=atoi(str[50]); + // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per for(i=0;i<3;i++){ - mob_db[class].mvpitem[i].nameid=atoi(str[47+i*2]); - mob_db[class].mvpitem[i].p=atoi(str[48+i*2])*battle_config.mvp_item_rate/100; + int rate=atoi(str[52+i*2])*battle_config.mvp_item_rate/100; //idea of the fix from Freya + mob_db[class_].mvpitem[i].nameid=atoi(str[51+i*2]); + mob_db[class_].mvpitem[i].p= (rate < battle_config.item_drop_mvp_min) + ? battle_config.item_drop_mvp_min : (rate > battle_config.item_drop_mvp_max) + ? battle_config.item_drop_mvp_max : rate; } for(i=0;i<MAX_RANDOMMONSTER;i++) - mob_db[class].summonper[i]=0; - mob_db[class].maxskill=0; - - mob_db[class].sex=0; - mob_db[class].hair=0; - mob_db[class].hair_color=0; - mob_db[class].weapon=0; - mob_db[class].shield=0; - mob_db[class].head_top=0; - mob_db[class].head_mid=0; - mob_db[class].head_buttom=0; - mob_db[class].clothes_color=0; //Add for player monster dye - Valaris + mob_db[class_].summonper[i]=0; + mob_db[class_].maxskill=0; + + mob_db[class_].sex=0; + mob_db[class_].hair=0; + mob_db[class_].hair_color=0; + mob_db[class_].weapon=0; + mob_db[class_].shield=0; + mob_db[class_].head_top=0; + mob_db[class_].head_mid=0; + mob_db[class_].head_buttom=0; + mob_db[class_].clothes_color=0; //Add for player monster dye - Valaris } fclose(fp); - printf("read %s done\n",filename[i]); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n",filename[i]); + ShowStatus(tmp_output); } return 0; } @@ -3899,7 +4051,7 @@ static int mob_readdb_mobavail(void) FILE *fp; char line[1024]; int ln=0; - int class,j,k; + int class_,j,k; char *str[20],*p,*np; if( (fp=fopen("db/mob_avail.txt","r"))==NULL ){ @@ -3918,39 +4070,42 @@ static int mob_readdb_mobavail(void) *np=0; p=np+1; } else - str[j]=p; - } + str[j]=p; + } if(str[0]==NULL) continue; - class=atoi(str[0]); - - if(class<=1000 || class>2000) // ’l‚ªˆÙí‚Ȃ爗‚µ‚È‚¢B + class_=atoi(str[0]); + if(class_<=1000 || class_>MAX_MOB_DB) // ’l‚ªˆÙí‚Ȃ爗‚µ‚È‚¢B continue; + k=atoi(str[1]); - if(k >= 0) - mob_db[class].view_class=k; - - if((mob_db[class].view_class < 24) || (mob_db[class].view_class > 4000)) { - mob_db[class].sex=atoi(str[2]); - mob_db[class].hair=atoi(str[3]); - mob_db[class].hair_color=atoi(str[4]); - mob_db[class].weapon=atoi(str[5]); - mob_db[class].shield=atoi(str[6]); - mob_db[class].head_top=atoi(str[7]); - mob_db[class].head_mid=atoi(str[8]); - mob_db[class].head_buttom=atoi(str[9]); - mob_db[class].option=atoi(str[10])&~0x46; - mob_db[class].clothes_color=atoi(str[11]); // Monster player dye option - Valaris + if(k < 0) + continue; + if (j > 3 && k > 23 && k < 69) + k += 3977; // advanced job/baby class + mob_db[class_].view_class=k; + + if((k < 24) || (k > 4000)) { + mob_db[class_].sex=atoi(str[2]); + mob_db[class_].hair=atoi(str[3]); + mob_db[class_].hair_color=atoi(str[4]); + mob_db[class_].weapon=atoi(str[5]); + mob_db[class_].shield=atoi(str[6]); + mob_db[class_].head_top=atoi(str[7]); + mob_db[class_].head_mid=atoi(str[8]); + mob_db[class_].head_buttom=atoi(str[9]); + mob_db[class_].option=atoi(str[10])&~0x46; + mob_db[class_].clothes_color=atoi(str[11]); // Monster player dye option - Valaris } - - else if(atoi(str[2]) > 0) mob_db[class].equip=atoi(str[2]); // mob equipment [Valaris] + else if(atoi(str[2]) > 0) mob_db[class_].equip=atoi(str[2]); // mob equipment [Valaris] ln++; } fclose(fp); - printf("read db/mob_avail.txt done (count=%d)\n",ln); + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/mob_avail.txt"); + ShowStatus(tmp_output); return 0; } @@ -3978,7 +4133,7 @@ static int mob_read_randommonster(void) return -1; } while(fgets(line,1020,fp)){ - int class,per; + int class_,per; if(line[0] == '/' && line[1] == '/') continue; memset(str,0,sizeof(str)); @@ -3991,13 +4146,14 @@ static int mob_read_randommonster(void) if(str[0]==NULL || str[2]==NULL) continue; - class = atoi(str[0]); + class_ = atoi(str[0]); per=atoi(str[2]); - if((class>1000 && class<=2000) || class==0) - mob_db[class].summonper[i]=per; + if((class_>1000 && class_<=MAX_MOB_DB) || class_==0) + mob_db[class_].summonper[i]=per; } fclose(fp); - printf("read %s done\n",mobfile[i]); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n",mobfile[i]); + ShowStatus(tmp_output); } return 0; } @@ -4116,7 +4272,10 @@ static int mob_readskilldb(void) ms->state=state[j].id; } ms->skill_id=atoi(sp[3]); - ms->skill_lv=atoi(sp[4]); + j=atoi(sp[4]); + if (j<=0 || j>MAX_SKILL_DB) + continue; + ms->skill_lv=j; ms->permillage=atoi(sp[5]); ms->casttime=atoi(sp[6]); ms->delay=atoi(sp[7]); @@ -4149,21 +4308,61 @@ static int mob_readskilldb(void) mob_db[mob_id].maxskill=i+1; } fclose(fp); - printf("read %s done\n",filename[x]); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n",filename[x]); + ShowStatus(tmp_output); } return 0; } - -void mob_reload(void) +/*========================================== + * db/mob_race_db.txt reading + *------------------------------------------ + */ +static int mob_readdb_race(void) { - /* + FILE *fp; + char line[1024]; + int race,j,k; + char *str[20],*p,*np; - <empty monster database> - mob_read(); + if( (fp=fopen("db/mob_race2_db.txt","r"))==NULL ){ + printf("can't read db/mob_race2_db.txt\n"); + return -1; + } + + while(fgets(line,1020,fp)){ + if(line[0]=='/' && line[1]=='/') + continue; + memset(str,0,sizeof(str)); - */ + for(j=0,p=line;j<12;j++){ + if((np=strchr(p,','))!=NULL){ + str[j]=p; + *np=0; + p=np+1; + } else + str[j]=p; + } + if(str[0]==NULL) + continue; + + race=atoi(str[0]); + if (race < 0 || race >= MAX_MOB_RACE_DB) + continue; - do_init_mob(); + for (j=1; j<20; j++) { + if (!str[j]) + break; + k=atoi(str[j]); + if (k < 1000 || k > MAX_MOB_DB) + continue; + mob_db[k].race2 = race; + //mob_race_db[race][j] = k; + } + } + fclose(fp); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/mob_race2_db.txt"); + ShowStatus(tmp_output); + return 0; } #ifndef TXT_ONLY @@ -4174,11 +4373,12 @@ void mob_reload(void) static int mob_read_sqldb(void) { char line[1024]; - int i,class,ln=0; - char *str[55],*p,*np; - + int i,class_; + long unsigned int ln=0; + char *str[60],*p,*np; // 55->60 Lupus + memset(mob_db,0,sizeof(mob_db)); - + sprintf (tmp_sql, "SELECT * FROM `%s`",mob_db_db); if(mysql_query(&mmysql_handle, tmp_sql) ) { printf("DB server Error (select %s to Memory)- %s\n",mob_db_db,mysql_error(&mmysql_handle) ); @@ -4186,7 +4386,7 @@ static int mob_read_sqldb(void) sql_res = mysql_store_result(&mmysql_handle); if (sql_res) { while((sql_row = mysql_fetch_row(sql_res))){ - sprintf(line,"%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", + sprintf(line,"%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", sql_row[0],sql_row[1],sql_row[2],sql_row[3],sql_row[4], sql_row[5],sql_row[6],sql_row[7],sql_row[8],sql_row[9], sql_row[10],sql_row[11],sql_row[12],sql_row[13],sql_row[14], @@ -4197,9 +4397,10 @@ static int mob_read_sqldb(void) sql_row[35],sql_row[36],sql_row[37],sql_row[38],sql_row[39], sql_row[40],sql_row[41],sql_row[42],sql_row[43],sql_row[44], sql_row[45],sql_row[46],sql_row[47],sql_row[48],sql_row[49], - sql_row[50],sql_row[51],sql_row[52]); + sql_row[50],sql_row[51],sql_row[52],sql_row[53],sql_row[54], + sql_row[55],sql_row[56]); - for(i=0,p=line;i<55;i++){ + for(i=0,p=line;i<57;i++){ if((np=strchr(p,','))!=NULL){ str[i]=p; *np=0; @@ -4207,109 +4408,141 @@ static int mob_read_sqldb(void) } else str[i]=p; } - - class=atoi(str[0]); - if(class<=1000 || class>2000) + + class_=atoi(str[0]); + if(class_<=1000 || class_>MAX_MOB_DB) continue; - + ln++; - - mob_db[class].view_class=class; - memcpy(mob_db[class].name,str[1],24); - memcpy(mob_db[class].jname,str[2],24); - mob_db[class].lv=atoi(str[3]); - mob_db[class].max_hp=atoi(str[4]); - mob_db[class].max_sp=atoi(str[5]); - mob_db[class].base_exp=atoi(str[6])* - battle_config.base_exp_rate/100; - if(mob_db[class].base_exp <= 0) - mob_db[class].base_exp = 1; - mob_db[class].job_exp=atoi(str[7])* - battle_config.job_exp_rate/100; - if(mob_db[class].job_exp <= 0) - mob_db[class].job_exp = 1; - mob_db[class].range=atoi(str[8]); - mob_db[class].atk1=atoi(str[9]); - mob_db[class].atk2=atoi(str[10]); - mob_db[class].def=atoi(str[11]); - mob_db[class].mdef=atoi(str[12]); - mob_db[class].str=atoi(str[13]); - mob_db[class].agi=atoi(str[14]); - mob_db[class].vit=atoi(str[15]); - mob_db[class].int_=atoi(str[16]); - mob_db[class].dex=atoi(str[17]); - mob_db[class].luk=atoi(str[18]); - mob_db[class].range2=atoi(str[19]); - mob_db[class].range3=atoi(str[20]); - mob_db[class].size=atoi(str[21]); - mob_db[class].race=atoi(str[22]); - mob_db[class].element=atoi(str[23]); - mob_db[class].mode=atoi(str[24]); - mob_db[class].speed=atoi(str[25]); - mob_db[class].adelay=atoi(str[26]); - mob_db[class].amotion=atoi(str[27]); - mob_db[class].dmotion=atoi(str[28]); - - for(i=0;i<8;i++){ + + mob_db[class_].view_class=class_; + memcpy(mob_db[class_].name,str[1],24); + memcpy(mob_db[class_].jname,str[2],24); + mob_db[class_].lv=atoi(str[3]); + mob_db[class_].max_hp=atoi(str[4]); + mob_db[class_].max_sp=atoi(str[5]); + + mob_db[class_].base_exp = atoi(str[6]); + if (mob_db[class_].base_exp <= 0) + mob_db[class_].base_exp = 0; + else if (mob_db[class_].base_exp * battle_config.base_exp_rate / 100 > 1000000000 || + mob_db[class_].base_exp * battle_config.base_exp_rate / 100 < 0) + mob_db[class_].base_exp = 1000000000; + else { + mob_db[class_].base_exp = mob_db[class_].base_exp * battle_config.base_exp_rate / 100; + if (mob_db[class_].base_exp < 1) + mob_db[class_].base_exp = 1; + } + mob_db[class_].job_exp = atoi(str[7]); + if (mob_db[class_].job_exp <= 0) + mob_db[class_].job_exp = 0; + else if (mob_db[class_].job_exp * battle_config.job_exp_rate / 100 > 1000000000 || + mob_db[class_].job_exp * battle_config.job_exp_rate / 100 < 0) + mob_db[class_].job_exp = 1000000000; + else { + mob_db[class_].job_exp = mob_db[class_].job_exp * battle_config.job_exp_rate / 100; + if (mob_db[class_].job_exp < 1) + mob_db[class_].job_exp = 1; + } + + mob_db[class_].range=atoi(str[8]); + mob_db[class_].atk1=atoi(str[9]); + mob_db[class_].atk2=atoi(str[10]); + mob_db[class_].def=atoi(str[11]); + mob_db[class_].mdef=atoi(str[12]); + mob_db[class_].str=atoi(str[13]); + mob_db[class_].agi=atoi(str[14]); + mob_db[class_].vit=atoi(str[15]); + mob_db[class_].int_=atoi(str[16]); + mob_db[class_].dex=atoi(str[17]); + mob_db[class_].luk=atoi(str[18]); + mob_db[class_].range2=atoi(str[19]); + mob_db[class_].range3=atoi(str[20]); + mob_db[class_].size=atoi(str[21]); + mob_db[class_].race=atoi(str[22]); + mob_db[class_].element=atoi(str[23]); + mob_db[class_].mode=atoi(str[24]); + mob_db[class_].speed=atoi(str[25]); + mob_db[class_].adelay=atoi(str[26]); + mob_db[class_].amotion=atoi(str[27]); + mob_db[class_].dmotion=atoi(str[28]); + + for(i=0;i<10;i++){ // 8 -> 10 Lupus int rate = 0,type,ratemin,ratemax; - mob_db[class].dropitem[i].nameid=atoi(str[29+i*2]); - type = itemdb_type(mob_db[class].dropitem[i].nameid); + mob_db[class_].dropitem[i].nameid=atoi(str[29+i*2]); + type = itemdb_type(mob_db[class_].dropitem[i].nameid); if (type == 0) { // Added by Valaris - rate = battle_config.item_rate_heal; + rate = battle_config.item_rate_heal * atoi(str[30+i*2]) / 100; ratemin = battle_config.item_drop_heal_min; ratemax = battle_config.item_drop_heal_max; } else if (type == 2) { - rate = battle_config.item_rate_use; + rate = battle_config.item_rate_use * atoi(str[30+i*2]) / 100; ratemin = battle_config.item_drop_use_min; ratemax = battle_config.item_drop_use_max; // End } else if (type == 4 || type == 5 || type == 8) { // Changed to include Pet Equip - rate = battle_config.item_rate_equip; + rate = battle_config.item_rate_equip * atoi(str[30+i*2]) / 100; ratemin = battle_config.item_drop_equip_min; ratemax = battle_config.item_drop_equip_max; } else if (type == 6) { - rate = battle_config.item_rate_card; + rate = battle_config.item_rate_card * atoi(str[30+i*2]) / 100; ratemin = battle_config.item_drop_card_min; ratemax = battle_config.item_drop_card_max; } else { - rate = battle_config.item_rate_common; + rate = battle_config.item_rate_common * atoi(str[30+i*2]) / 100; ratemin = battle_config.item_drop_common_min; ratemax = battle_config.item_drop_common_max; } - rate = (rate / 100) * atoi(str[30+i*2]); - rate = (rate < ratemin)? ratemin: (rate > ratemax)? ratemax: rate; - mob_db[class].dropitem[i].p = rate; + + mob_db[class_].dropitem[i].p = (rate < ratemin) ? ratemin : (rate > ratemax) ? ratemax: rate; } - - mob_db[class].mexp=atoi(str[45])*battle_config.mvp_exp_rate/100; - mob_db[class].mexpper=atoi(str[46]); + // MVP EXP Bonus, Chance: MEXP,ExpPer + mob_db[class_].mexp=atoi(str[49])*battle_config.mvp_exp_rate/100; + mob_db[class_].mexpper=atoi(str[50]); + // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per for(i=0;i<3;i++){ - mob_db[class].mvpitem[i].nameid=atoi(str[47+i*2]); - mob_db[class].mvpitem[i].p=atoi(str[48+i*2])*battle_config.mvp_item_rate/100; + mob_db[class_].mvpitem[i].nameid=atoi(str[51+i*2]); + mob_db[class_].mvpitem[i].p=atoi(str[52+i*2])*battle_config.mvp_item_rate/100; } for(i=0;i<MAX_RANDOMMONSTER;i++) - mob_db[class].summonper[i]=0; - mob_db[class].maxskill=0; - - mob_db[class].sex=0; - mob_db[class].hair=0; - mob_db[class].hair_color=0; - mob_db[class].weapon=0; - mob_db[class].shield=0; - mob_db[class].head_top=0; - mob_db[class].head_mid=0; - mob_db[class].head_buttom=0; + mob_db[class_].summonper[i]=0; + mob_db[class_].maxskill=0; + + mob_db[class_].sex=0; + mob_db[class_].hair=0; + mob_db[class_].hair_color=0; + mob_db[class_].weapon=0; + mob_db[class_].shield=0; + mob_db[class_].head_top=0; + mob_db[class_].head_mid=0; + mob_db[class_].head_buttom=0; } mysql_free_result(sql_res); - printf("read %s done (count=%d)\n",mob_db_db,ln); + sprintf(tmp_output,"Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,mob_db_db); + ShowStatus(tmp_output); } return 0; } - #endif /* not TXT_ONLY */ + +void mob_reload(void) +{ +#ifndef TXT_ONLY + if(db_use_sqldbs) + mob_read_sqldb(); + else +#endif /* TXT_ONLY */ + mob_readdb(); + + mob_readdb_mobavail(); + mob_read_randommonster(); + mob_readskilldb(); + mob_readdb_race(); +} + /*========================================== * Circumference initialization of mob *------------------------------------------ @@ -4319,13 +4552,14 @@ int do_init_mob(void) #ifndef TXT_ONLY if(db_use_sqldbs) mob_read_sqldb(); - else + else #endif /* TXT_ONLY */ mob_readdb(); mob_readdb_mobavail(); mob_read_randommonster(); mob_readskilldb(); + mob_readdb_race(); add_timer_func_list(mob_timer,"mob_timer"); add_timer_func_list(mob_delayspawn,"mob_delayspawn"); diff --git a/src/map/mob.h b/src/map/mob.h index e5a83be0f..6613c5b6b 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -3,6 +3,10 @@ #define _MOB_H_ #define MAX_RANDOMMONSTER 3 +#define MAX_MOB_RACE_DB 6 +#define MAX_MOB_DB 2000 /* Change this to increase the table size in your mob_db to accomodate + numbers more than 2000 for mobs if you want to (and know what you're doing). + Be sure to note that 4001 to 4047 are for advanced classes. */ struct mob_skill { short state; @@ -26,9 +30,10 @@ struct mob_db { int str,agi,vit,int_,dex,luk; int range,range2,range3; int size,race,element,mode; + short race2; // celest int speed,adelay,amotion,dmotion; int mexp,mexpper; - struct { int nameid,p; } dropitem[8]; + struct { int nameid,p; } dropitem[10]; //8 -> 10 Lupus struct { int nameid,p; } mvpitem[3]; int view_class,sex; short hair,hair_color,weapon,shield,head_top,head_mid,head_buttom,option,clothes_color; // [Valaris] @@ -72,32 +77,35 @@ enum { }; enum { - MSS_IDLE, // ‘Ò‹@ - MSS_WALK, // ˆÚ“® - MSS_ATTACK, // UŒ‚ - MSS_DEAD, // Ž€–S - MSS_LOOT, // ƒ‹[ƒg - MSS_CHASE, // “ËŒ‚ + MSS_IDLE, // ?@ + MSS_WALK, // ? + MSS_ATTACK, // U + MSS_DEAD, // S + MSS_LOOT, // [g + MSS_CHASE, // ? }; int mobdb_searchname(const char *str); int mobdb_checkid(const int id); int mob_once_spawn(struct map_session_data *sd,char *mapname, - int x,int y,const char *mobname,int class,int amount,const char *event); + int x,int y,const char *mobname,int class_,int amount,const char *event); int mob_once_spawn_area(struct map_session_data *sd,char *mapname, int x0,int y0,int x1,int y1, - const char *mobname,int class,int amount,const char *event); + const char *mobname,int class_,int amount,const char *event); int mob_spawn_guardian(struct map_session_data *sd,char *mapname, // Spawning Guardians [Valaris] - int x,int y,const char *mobname,int class,int amount,const char *event,int guardian); // Spawning Guardians [Valaris] + int x,int y,const char *mobname,int class_,int amount,const char *event,int guardian); // Spawning Guardians [Valaris] int mob_walktoxy(struct mob_data *md,int x,int y,int easy); +//int mob_randomwalk(struct mob_data *md,int tick); +//int mob_can_move(struct mob_data *md); int mob_target(struct mob_data *md,struct block_list *bl,int dist); int mob_stop_walking(struct mob_data *md,int type); int mob_stopattack(struct mob_data *); int mob_spawn(int); +int mob_setdelayspawn(int); int mob_damage(struct block_list *,struct mob_data*,int,int); int mob_changestate(struct mob_data *md,int state,int type); int mob_heal(struct mob_data*,int); @@ -116,8 +124,9 @@ short mob_get_clothes_color(int); //player mob dye [Valaris] int mob_get_equip(int); // mob equip [Valaris] int do_init_mob(void); +void mob_unload(struct mob_data *md); +int mob_remove_map(struct mob_data *md, int type); int mob_delete(struct mob_data *md); -int mob_catch_delete(struct mob_data *md,int type); int mob_timer_delete(int tid, unsigned int tick, int id, int data); int mob_deleteslave(struct mob_data *md); @@ -132,6 +141,7 @@ int mobskill_event(struct mob_data *md,int flag); int mobskill_castend_id( int tid, unsigned int tick, int id,int data ); int mobskill_castend_pos( int tid, unsigned int tick, int id,int data ); int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag); +int mob_countslave(struct mob_data *md); int mob_gvmobcheck(struct map_session_data *sd, struct block_list *bl); void mob_reload(void); diff --git a/src/map/npc.c b/src/map/npc.c index b1f9c54ec..069597f83 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -15,29 +15,39 @@ #include "clif.h" #include "intif.h" #include "pc.h" +#include "status.h" #include "itemdb.h" #include "script.h" #include "mob.h" #include "pet.h" #include "battle.h" #include "skill.h" +#include "grfio.h" +#include "showmsg.h" #ifdef MEMWATCH #include "memwatch.h" #endif - +#ifdef _WIN32 +#undef isspace +#define isspace(x) (x == ' ' || x == '\t') +#endif struct npc_src_list { struct npc_src_list * next; - struct npc_src_list * prev; +// struct npc_src_list * prev; //[Shinomori] char name[4]; -} ; +}; -static struct npc_src_list *npc_src_first,*npc_src_last; +static struct npc_src_list *npc_src_first=NULL; +static struct npc_src_list *npc_src_last=NULL; static int npc_id=START_NPC_NUM; -static int npc_warp,npc_shop,npc_script,npc_mob; - +static int npc_warp=0; +static int npc_shop=0; +static int npc_script=0; +static int npc_mob=0; +char *current_file = NULL; int npc_get_new_npc_id(void){ return npc_id++; } static struct dbt *ev_db; @@ -62,31 +72,33 @@ int npc_enable_sub( struct block_list *bl, va_list ap ) { struct map_session_data *sd; struct npc_data *nd; - char *name=(char *)aCalloc(50,sizeof(char)); + //char *name=(char *)aCallocA(50,sizeof(char)); // fixed [Shinomori] nullpo_retr(0, bl); nullpo_retr(0, ap); nullpo_retr(0, nd=va_arg(ap,struct npc_data *)); if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)){ + char name[50]; // need 24 + 9 for the "::OnTouch" if (nd->flag&1) // –³Œø‰»‚³‚ê‚Ä‚¢‚é return 1; - memcpy(name,nd->name,50); if(sd->areanpc_id==nd->bl.id) return 1; sd->areanpc_id=nd->bl.id; - npc_event(sd,strcat(name,"::OnTouch"),0); + + sprintf(name,"%s::OnTouch", nd->name); + npc_event(sd,name,0); } - free(name); + //aFree(name); return 0; } int npc_enable(const char *name,int flag) { - struct npc_data *nd=strdb_search(npcname_db,name); + struct npc_data *nd= (struct npc_data *) strdb_search(npcname_db,name); if (nd==NULL) return 0; - + if (flag&1) { // —LŒø‰» nd->flag&=~1; clif_spawnnpc(nd); @@ -114,8 +126,17 @@ int npc_enable(const char *name,int flag) */ struct npc_data* npc_name2id(const char *name) { - return strdb_search(npcname_db,name); + return (struct npc_data *) strdb_search(npcname_db,name); +} + +void ev_release(struct dbn *db, int which) +{ + if (which & 0x1) + aFree(db->key); + if (which & 0x2) + aFree(db->data); } + /*========================================== * ƒCƒxƒ“ƒgƒLƒ…[‚̃Cƒxƒ“ƒgˆ— *------------------------------------------ @@ -126,47 +147,69 @@ int npc_event_dequeue(struct map_session_data *sd) sd->npc_id=0; if (sd->eventqueue[0][0]) { // ƒLƒ…[‚̃Cƒxƒ“ƒgˆ— - char *name=(char *)aCalloc(50,sizeof(char)); - int i; + size_t ev; - memcpy(name,sd->eventqueue[0],50); - for(i=MAX_EVENTQUEUE-2;i>=0;i--) - memcpy(sd->eventqueue[i],sd->eventqueue[i+1],50); - add_timer(gettick()+100,npc_event_timer,sd->bl.id,(int)name); + // find an empty place in eventtimer list + for(ev=0;ev<MAX_EVENTTIMER;ev++) + if( sd->eventtimer[ev]==-1 ) + break; + if(ev<MAX_EVENTTIMER) + { // generate and insert the timer + int i; + // copy the first event name + char *name=(char *)aMalloc(50*sizeof(char)); + memcpy(name,sd->eventqueue[0],50); + // shift queued events down by one + for(i=1;i<MAX_EVENTQUEUE;i++) + memcpy(sd->eventqueue[i-1],sd->eventqueue[i],50); + // clear the last event + sd->eventqueue[MAX_EVENTQUEUE-1][0]=0; + // add the timer + sd->eventtimer[ev]=add_timer(gettick()+100,pc_eventtimer,sd->bl.id,(int)name);//!!todo!! + + }else + printf("npc_event_dequeue: event timer is full !\n"); } return 0; } -int npc_delete(struct npc_data *nd) -{ - nullpo_retr(1, nd); - - if(nd->bl.prev == NULL) - return 1; - - clif_clearchar_area(&nd->bl,1); - map_delblock(&nd->bl); - return 0; -} - /*========================================== * ƒCƒxƒ“ƒg‚Ì’x‰„ŽÀs *------------------------------------------ */ int npc_event_timer(int tid,unsigned int tick,int id,int data) { + char *eventname = (char *)data; + struct event_data *ev = (struct event_data *)strdb_search(ev_db,eventname); + struct npc_data *nd; struct map_session_data *sd=map_id2sd(id); - if (sd==NULL) - return 0; - - npc_event(sd,(const char *)data,0); - free((void*)data); + size_t i; + + if((ev==NULL || (nd=ev->nd)==NULL)) + { + if(battle_config.error_log) + printf("npc_event: event not found [%s]\n",eventname); + } + else + { + for(i=0;i<MAX_EVENTTIMER;i++) { + if( nd->eventtimer[i]==tid ) { + nd->eventtimer[i]=-1; + npc_event(sd,eventname,0); // sd NULL check is within + break; + } + } + if(i==MAX_EVENTTIMER && battle_config.error_log) + printf("npc_event_timer: event timer not found [%s]!\n",eventname); + } + + aFree(eventname); return 0; } int npc_timer_event(const char *eventname) // Added by RoVeRT { - struct event_data *ev=strdb_search(ev_db,eventname); + struct event_data *ev=(struct event_data *) strdb_search(ev_db,eventname); struct npc_data *nd; // int xs,ys; @@ -220,7 +263,7 @@ int npc_timer(int tid,unsigned int tick,int id,int data) // Added by RoVeRT { strdb_foreach(npcname_db,npc_timer_sub); - free((void*)data); + aFree((void*)data); return 0; }*/ /*========================================== @@ -233,14 +276,14 @@ int npc_event_export(void *key,void *data,va_list ap) char *lname=(char *)key; int pos=(int)data; struct npc_data *nd=va_arg(ap,struct npc_data *); - + if ((lname[0]=='O' || lname[0]=='o')&&(lname[1]=='N' || lname[1]=='n')) { struct event_data *ev; char *buf; char *p=strchr(lname,':'); // ƒGƒNƒXƒ|[ƒg‚³‚ê‚é - ev=calloc(sizeof(struct event_data), 1); - buf=calloc(50, 1); + ev=(struct event_data *) aCalloc(sizeof(struct event_data), 1); + buf=(char *) aCallocA(50, 1); if (ev==NULL || buf==NULL) { printf("npc_event_export: out of memory !\n"); exit(1); @@ -261,62 +304,6 @@ int npc_event_export(void *key,void *data,va_list ap) return 0; } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /*========================================== * ‘S‚Ä‚ÌNPC‚ÌOn*ƒCƒxƒ“ƒgŽÀs *------------------------------------------ @@ -326,29 +313,39 @@ int npc_event_doall_sub(void *key,void *data,va_list ap) char *p=(char *)key; struct event_data *ev; int *c; + int rid; const char *name; nullpo_retr(0, ev=(struct event_data *)data); nullpo_retr(0, ap); nullpo_retr(0, c=va_arg(ap,int *)); - name=va_arg(ap,const char *); + rid=va_arg(ap, int); if( (p=strchr(p,':')) && p && strcmpi(name,p)==0 ){ - run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id); + run_script(ev->nd->u.scr.script,ev->pos,rid,ev->nd->bl.id); (*c)++; } - + return 0; } int npc_event_doall(const char *name) { int c=0; char buf[64]="::"; - + + strncpy(buf+2,name,62); + strdb_foreach(ev_db,npc_event_doall_sub,&c,buf,0); + return c; +} +int npc_event_doall_id(const char *name, int rid) +{ + int c=0; + char buf[64]="::"; + strncpy(buf+2,name,62); - strdb_foreach(ev_db,npc_event_doall_sub,&c,buf); - return c; + strdb_foreach(ev_db,npc_event_doall_sub,&c,buf,rid); + return c; } int npc_event_do_sub(void *key,void *data,va_list ap) @@ -374,7 +371,7 @@ int npc_event_do_sub(void *key,void *data,va_list ap) int npc_event_do(const char *name) { int c=0; - + if (*name==':' && name[1]==':') { return npc_event_doall(name+2); } @@ -394,7 +391,7 @@ int npc_event_do_clock(int tid,unsigned int tick,int id,int data) char buf[64]; char *day=""; int c=0; - + time(&timer); t=localtime(&timer); @@ -407,7 +404,7 @@ int npc_event_do_clock(int tid,unsigned int tick,int id,int data) case 5: day = "Fri"; break; case 6: day = "Sat"; break; } - + if (t->tm_min != ev_tm_b.tm_min ) { sprintf(buf,"OnMinute%02d",t->tm_min); c+=npc_event_doall(buf); @@ -433,8 +430,10 @@ int npc_event_do_clock(int tid,unsigned int tick,int id,int data) */ int npc_event_do_oninit(void) { - int c = npc_event_doall("OnInit"); - printf("npc: OnInit Event done. (%d npc)\n",c); +// int c = npc_event_doall("OnInit"); + sprintf(tmp_output,"Event '"CL_WHITE"OnInit"CL_RESET"' executed with '" + CL_WHITE"%d"CL_RESET"' NPCs.\n",npc_event_doall("OnInit")); + ShowStatus(tmp_output); add_timer_interval(gettick()+100, npc_event_do_clock,0,0,1000); @@ -452,7 +451,7 @@ int npc_addeventtimer(struct npc_data *nd,int tick,const char *name) if( nd->eventtimer[i]==-1 ) break; if(i<MAX_EVENTTIMER){ - char *evname=malloc(24); + char *evname=(char *) aMallocA(24); if(evname==NULL){ printf("npc_addeventtimer: out of memory !\n");exit(1); } @@ -493,33 +492,33 @@ int npc_cleareventtimer(struct npc_data *nd) int npc_do_ontimer_sub(void *key,void *data,va_list ap) { - char *p=(char *)key; - struct event_data *ev=(struct event_data *)data; - int *c=va_arg(ap,int *); + char *p = (char *)key; + struct event_data *ev = (struct event_data *)data; + int *c = va_arg(ap,int *); // struct map_session_data *sd=va_arg(ap,struct map_session_data *); - int option=va_arg(ap,int); - int tick=0; + int option = va_arg(ap,int); + int tick = 0; char temp[10]; char event[50]; - if(ev->nd->bl.id==(int)*c && (p=strchr(p,':')) && p && strnicmp("::OnTimer",p,8)==0 ){ - sscanf(&p[9],"%s",temp); - tick=atoi(temp); + if(ev->nd->bl.id == (int)*c && (p = strchr(p,':')) && strnicmp("::OnTimer",p,8) == 0){ + sscanf(&p[9], "%s", temp); + tick = atoi(temp); - strcpy( event, ev->nd->name); - strcat( event, p); + strcpy(event, ev->nd->name); + strcat(event, p); if (option!=0) { - npc_addeventtimer(ev->nd,tick,event); + npc_addeventtimer(ev->nd, tick, event); } else { - npc_deleventtimer(ev->nd,event); + npc_deleventtimer(ev->nd, event); } } return 0; } -int npc_do_ontimer(int npc_id, struct map_session_data *sd, int option) +int npc_do_ontimer(int npc_id, int option) { - strdb_foreach(ev_db,npc_do_ontimer_sub,&npc_id,sd,option); + strdb_foreach(ev_db, npc_do_ontimer_sub, &npc_id, option); return 0; } /*========================================== @@ -533,13 +532,13 @@ int npc_timerevent_import(void *key,void *data,va_list ap) int pos=(int)data; struct npc_data *nd=va_arg(ap,struct npc_data *); int t=0,i=0; - + if(sscanf(lname,"OnTimer%d%n",&t,&i)==1 && lname[i]==':') { // ƒ^ƒCƒ}[ƒCƒxƒ“ƒg struct npc_timerevent_list *te=nd->u.scr.timer_event; int j,i=nd->u.scr.timeramount; - if(te==NULL) te=malloc(sizeof(struct npc_timerevent_list)); - else te=realloc( te, sizeof(struct npc_timerevent_list) * (i+1) ); + if(te==NULL) te=(struct npc_timerevent_list*)aMallocA(sizeof(struct npc_timerevent_list)); + else te= (struct npc_timerevent_list*)aRealloc( te, sizeof(struct npc_timerevent_list) * (i+1) ); if(te==NULL){ printf("npc_timerevent_import: out of memory !\n"); exit(1); @@ -573,7 +572,7 @@ int npc_timerevent(int tid,unsigned int tick,int id,int data) nd->u.scr.timertick=tick; te=nd->u.scr.timer_event+ nd->u.scr.nexttimer; nd->u.scr.timerid = -1; - + t = nd->u.scr.timer+=data; nd->u.scr.nexttimer++; if( nd->u.scr.timeramount>nd->u.scr.nexttimer ){ @@ -581,14 +580,14 @@ int npc_timerevent(int tid,unsigned int tick,int id,int data) nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,id,next); } - run_script(nd->u.scr.script,te->pos,0,nd->bl.id); + run_script(nd->u.scr.script,te->pos,nd->u.scr.rid,nd->bl.id); return 0; } /*========================================== * ƒ^ƒCƒ}[ƒCƒxƒ“ƒgŠJŽn *------------------------------------------ */ -int npc_timerevent_start(struct npc_data *nd) +int npc_timerevent_start(struct npc_data *nd, int rid) { int j,n, next; @@ -597,17 +596,19 @@ int npc_timerevent_start(struct npc_data *nd) n=nd->u.scr.timeramount; if( nd->u.scr.nexttimer>=0 || n==0 ) return 0; - + for(j=0;j<n;j++){ if( nd->u.scr.timer_event[j].timer > nd->u.scr.timer ) break; } + if(j>=n) // check if there is a timer to use !!BEFORE!! you write stuff to the structures [Shinomori] + return 0; + nd->u.scr.nexttimer=j; nd->u.scr.timertick=gettick(); + if (rid >= 0) nd->u.scr.rid=rid; // changed to: attaching to given rid by default [Shinomori] + // if rid is less than 0 leave it unchanged [celest] - if(j>=n) - return 0; - next = nd->u.scr.timer_event[j].timer - nd->u.scr.timer; nd->u.scr.timerid = add_timer(gettick()+next,npc_timerevent,nd->bl.id,next); return 0; @@ -626,6 +627,7 @@ int npc_timerevent_stop(struct npc_data *nd) if(nd->u.scr.timerid!=-1) delete_timer(nd->u.scr.timerid,npc_timerevent); nd->u.scr.timerid = -1; + nd->u.scr.rid = 0; } return 0; } @@ -660,7 +662,7 @@ int npc_settimerevent_tick(struct npc_data *nd,int newtimer) npc_timerevent_stop(nd); nd->u.scr.timer=newtimer; if(flag>=0) - npc_timerevent_start(nd); + npc_timerevent_start(nd, -1); return 0; } @@ -670,7 +672,7 @@ int npc_settimerevent_tick(struct npc_data *nd,int newtimer) */ int npc_event(struct map_session_data *sd,const char *eventname,int mob_kill) { - struct event_data *ev=strdb_search(ev_db,eventname); + struct event_data *ev=(struct event_data *) strdb_search(ev_db,eventname); struct npc_data *nd; int xs,ys; char mobevent[100]; @@ -686,7 +688,7 @@ int npc_event(struct map_session_data *sd,const char *eventname,int mob_kill) if(mob_kill && (ev==NULL || (nd=ev->nd)==NULL)){ strcpy( mobevent, eventname); strcat( mobevent, "::OnMyMobDead"); - ev=strdb_search(ev_db,mobevent); + ev= (struct event_data *) strdb_search(ev_db,mobevent); if (ev==NULL || (nd=ev->nd)==NULL) { if (strnicmp(eventname,"GM_MONSTER",10)!=0) printf("npc_event: event not found [%s]\n",mobevent); @@ -732,7 +734,7 @@ int npc_event(struct map_session_data *sd,const char *eventname,int mob_kill) npc_event_dequeue(sd); return 0; } - + sd->npc_id=nd->bl.id; sd->npc_pos=run_script(nd->u.scr.script,ev->pos,sd->bl.id,nd->bl.id); return 0; @@ -753,7 +755,7 @@ int npc_command_sub(void *key,void *data,va_list ap) if (strcmp(command,temp)==0) run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id); } - + return 0; } @@ -782,7 +784,7 @@ int npc_touch_areanpc(struct map_session_data *sd,int m,int x,int y) f=0; continue; } - + switch(map[m].npc[i]->bl.subtype) { case WARP: xs=map[m].npc[i]->u.warp.xs; @@ -813,15 +815,18 @@ int npc_touch_areanpc(struct map_session_data *sd,int m,int x,int y) break; case SCRIPT: { - char *name=(char *)aCalloc(50,sizeof(char)); + //char *name=(char *)aCallocA(50,sizeof(char)); // fixed [Shinomori] + char name[50]; // need 24 max + 9 for "::OnTouch" - memcpy(name,map[m].npc[i]->name,50); - if(sd->areanpc_id==map[m].npc[i]->bl.id) + if(sd->areanpc_id == map[m].npc[i]->bl.id) return 1; - sd->areanpc_id=map[m].npc[i]->bl.id; - if(npc_event(sd,strcat(name,"::OnTouch"),0)>0) + sd->areanpc_id = map[m].npc[i]->bl.id; + + sprintf(name,"%s::OnTouch", map[m].npc[i]->name); + + if( npc_event(sd,name,0)>0 ) npc_click(sd,map[m].npc[i]->bl.id); - free(name); + //aFree(name); break; } } @@ -844,8 +849,8 @@ int npc_checknear(struct map_session_data *sd,int id) printf("no such npc : %d\n",id); return 1; } - - if (nd->class<0) // ƒCƒxƒ“ƒgŒn‚Íí‚ÉOK + + if (nd->class_<0) // ƒCƒxƒ“ƒgŒn‚Íí‚ÉOK return 0; // ƒGƒŠƒA”»’è @@ -858,6 +863,32 @@ int npc_checknear(struct map_session_data *sd,int id) } /*========================================== + * NPC‚̃I[ƒvƒ“ƒ`ƒƒƒbƒg”Œ¾ + *------------------------------------------ + */ +int npc_globalmessage(const char *name,char *mes) +{ + struct npc_data *nd=(struct npc_data *) strdb_search(npcname_db,name); + char temp[100]; + char ntemp[50]; + char *ltemp; + + if(nd==NULL) return 0; + if(name==NULL) return 0; + + ltemp=strchr(name,'#'); + if(ltemp!=NULL) { + strncpy(ntemp,name,ltemp - name); // 123#456 ‚Ì # ‚©‚çŒã‚ë‚ð휂·‚é + ntemp[ltemp - name]=0x00; // strncpy ‚̃oƒOHŽg‚¢•ûŠÔˆá‚Á‚Ä‚éH + } + + snprintf(temp, sizeof temp ,"%s : %s",ntemp,mes); + clif_GlobalMessage(&nd->bl,temp); + + return 0; +} + +/*========================================== * ƒNƒŠƒbƒNŽž‚ÌNPCˆ— *------------------------------------------ */ @@ -957,7 +988,7 @@ int npc_buylist(struct map_session_data *sd,int n,unsigned short *item_list) { struct npc_data *nd; double z; - int i,j,w,skill,itemamount=0,new=0; + int i,j,w,skill,itemamount=0,new_=0; nullpo_retr(3, sd); nullpo_retr(3, item_list); @@ -987,7 +1018,7 @@ int npc_buylist(struct map_session_data *sd,int n,unsigned short *item_list) case ADDITEM_EXIST: break; case ADDITEM_NEW: - new++; + new_++; break; case ADDITEM_OVERAMOUNT: return 2; @@ -999,7 +1030,7 @@ int npc_buylist(struct map_session_data *sd,int n,unsigned short *item_list) return 1; // zeny•s‘« if (w+sd->weight > sd->max_weight) return 2; // d—Ê’´‰ß - if (pc_inventoryblank(sd)<new) + if (pc_inventoryblank(sd)<new_) return 3; // Ží—Þ”’´‰ß pc_payzeny(sd,(int)z); @@ -1014,7 +1045,7 @@ int npc_buylist(struct map_session_data *sd,int n,unsigned short *item_list) } //¤lŒoŒ±’l -/* if ((sd->status.class == 5) || (sd->status.class == 10) || (sd->status.class == 18)) { +/* if ((sd->status.class_ == 5) || (sd->status.class_ == 10) || (sd->status.class_ == 18)) { z = z * pc_checkskill(sd,MC_DISCOUNT) / ((1 + 300 / itemamount) * 4000) * battle_config.shop_exp; pc_gainexp(sd,0,z); }*/ @@ -1022,7 +1053,7 @@ int npc_buylist(struct map_session_data *sd,int n,unsigned short *item_list) if (sd->status.skill[MC_DISCOUNT].flag != 0) skill = sd->status.skill[MC_DISCOUNT].flag - 2; if (skill > 0) { - z = (log(z * (double)skill) * (double)battle_config.shop_exp/100.); + z = z * (double)skill * (double)battle_config.shop_exp/10000.; if (z < 1) z = 1; pc_gainexp(sd,0,(int)z); @@ -1074,7 +1105,7 @@ int npc_selllist(struct map_session_data *sd,int n,unsigned short *item_list) } //¤lŒoŒ±’l -/* if ((sd->status.class == 5) || (sd->status.class == 10) || (sd->status.class == 18)) { +/* if ((sd->status.class_ == 5) || (sd->status.class_ == 10) || (sd->status.class_ == 18)) { z = z * pc_checkskill(sd,MC_OVERCHARGE) / ((1 + 500 / itemamount) * 4000) * battle_config.shop_exp ; pc_gainexp(sd,0,z); }*/ @@ -1082,7 +1113,7 @@ int npc_selllist(struct map_session_data *sd,int n,unsigned short *item_list) if (sd->status.skill[MC_OVERCHARGE].flag != 0) skill = sd->status.skill[MC_OVERCHARGE].flag - 2; if (skill > 0) { - z = (log(z * (double)skill) * (double)battle_config.shop_exp/100.); + z = z * (double)skill * (double)battle_config.shop_exp/10000.; if (z < 1) z = 1; pc_gainexp(sd,0,(int)z); @@ -1106,8 +1137,8 @@ static int calc_next_walk_step(struct npc_data *nd) if(nd->walkpath.path_pos>=nd->walkpath.path_len) return -1; if(nd->walkpath.path[nd->walkpath.path_pos]&1) - return battle_get_speed(&nd->bl)*14/10; - return battle_get_speed(&nd->bl); + return status_get_speed(&nd->bl)*14/10; + return status_get_speed(&nd->bl); } @@ -1118,7 +1149,7 @@ static int calc_next_walk_step(struct npc_data *nd) static int npc_walk(struct npc_data *nd,unsigned int tick,int data) { int moveblock; - int i,ctype; + int i; static int dirx[8]={0,-1,-1,-1,0,1,1,1}; static int diry[8]={1,1,0,-1,-1,-1,0,1}; int x,y,dx,dy; @@ -1143,8 +1174,7 @@ static int npc_walk(struct npc_data *nd,unsigned int tick,int data) x = nd->bl.x; y = nd->bl.y; - ctype = map_getcell(nd->bl.m,x,y); - if(ctype == 1 || ctype == 5) { + if(map_getcell(nd->bl.m,x,y,CELL_CHKNOPASS)) { npc_stop_walking(nd,1); return 0; } @@ -1152,8 +1182,7 @@ static int npc_walk(struct npc_data *nd,unsigned int tick,int data) dx = dirx[nd->dir]; dy = diry[nd->dir]; - ctype = map_getcell(nd->bl.m,x+dx,y+dy); - if(ctype == 1 || ctype == 5) { + if(map_getcell(nd->bl.m,x+dx,y+dy,CELL_CHKNOPASS)) { npc_walktoxy_sub(nd); return 0; } @@ -1183,7 +1212,7 @@ static int npc_walk(struct npc_data *nd,unsigned int tick,int data) if(nd->walkpath.path_pos>=nd->walkpath.path_len) clif_fixnpcpos(nd); // When npc stops, retransmission current of a position. - + } return 0; } @@ -1228,7 +1257,7 @@ static int npc_walktimer(int tid,unsigned int tick,int id,int data) if(nd->walktimer != tid){ return 0; } - + nd->walktimer=-1; if(nd->bl.prev == NULL) @@ -1293,7 +1322,7 @@ int npc_stop_walking(struct npc_data *nd,int type) if(nd->state.state == MS_WALK || nd->state.state == MS_IDLE) { int dx=0,dy=0; - + nd->walkpath.path_len=0; if(type&4){ dx=nd->to_x-nd->bl.x; @@ -1318,7 +1347,7 @@ int npc_stop_walking(struct npc_data *nd,int type) if(type&0x01) clif_fixnpcpos(nd); if(type&0x02) { - int delay=battle_get_dmotion(&nd->bl); + int delay=status_get_dmotion(&nd->bl); unsigned int tick = gettick(); if(nd->canmove_tick < tick) nd->canmove_tick = tick + delay; @@ -1327,6 +1356,56 @@ int npc_stop_walking(struct npc_data *nd,int type) return 0; } +int npc_remove_map (struct npc_data *nd) +{ + nullpo_retr(1, nd); + + if(nd->bl.prev == NULL) + return 1; + +#ifdef PCRE_SUPPORT + npc_chat_finalize(nd); +#endif + clif_clearchar_area(&nd->bl,2); + strdb_erase(npcname_db, nd->name); + map_delblock(&nd->bl); + map_deliddb(&nd->bl); + + return 0; +} + +int npc_unload(struct npc_data *nd) +{ + nullpo_retr (0, nd); + + if (nd->chat_id) { + struct chat_data *cd = (struct chat_data*)map_id2bl(nd->chat_id); + if (cd) aFree (cd); + cd = NULL; + } + if (nd->bl.subtype == SCRIPT) { + if (nd->u.scr.timerid != -1) + delete_timer(nd->u.scr.timerid, npc_timerevent); + npc_cleareventtimer (nd); + if (nd->u.scr.timer_event) + aFree(nd->u.scr.timer_event); + if (nd->u.scr.src_id == 0) { + if(nd->u.scr.script) { + aFree(nd->u.scr.script); + nd->u.scr.script = NULL; + } + if (nd->u.scr.label_list) { + aFree(nd->u.scr.label_list); + nd->u.scr.label_list = NULL; + } + } + } + npc_remove_map (nd); + aFree(nd); + nd = NULL; + + return 0; +} // // ‰Šú‰»ŠÖŒW @@ -1343,7 +1422,7 @@ void npc_clearsrcfile() while( p ) { struct npc_src_list *p2=p; p=p->next; - free(p2); + aFree(p2); } npc_src_first=NULL; npc_src_last=NULL; @@ -1354,7 +1433,7 @@ void npc_clearsrcfile() */ void npc_addsrcfile(char *name) { - struct npc_src_list *new; + struct npc_src_list *new_; size_t len; if ( strcmpi(name,"clear")==0 ) { @@ -1362,16 +1441,27 @@ void npc_addsrcfile(char *name) return; } - len = sizeof(*new) + strlen(name); - new=(struct npc_src_list *)aCalloc(1,len); - new->next = NULL; - strncpy(new->name,name,strlen(name)+1); + { + // prevent multiple insert of source files + struct npc_src_list *p=npc_src_first; + while( p ) + { // found the file, no need to insert it again + if( 0==strcmp(name,p->name) ) + return; + p=p->next; + } + } + + len = sizeof(*new_) + strlen(name); + new_=(struct npc_src_list *)aCalloc(1,len); + new_->next = NULL; + strncpy(new_->name,name,strlen(name)+1); if (npc_src_first==NULL) - npc_src_first = new; + npc_src_first = new_; if (npc_src_last) - npc_src_last->next = new; + npc_src_last->next = new_; - npc_src_last=new; + npc_src_last=new_; } /*========================================== * “ǂݞ‚Þnpcƒtƒ@ƒCƒ‹‚Ìíœ @@ -1391,7 +1481,7 @@ void npc_delsrcfile(char *name) *lp=p->next; if ( npc_src_last==p ) npc_src_last=pp; - free(p); + aFree(p); break; } } @@ -1432,9 +1522,9 @@ int npc_parse_warp(char *w1,char *w2,char *w3,char *w4) nd->chat_id=0; if (!battle_config.warp_point_debug) - nd->class=WARP_CLASS; + nd->class_=WARP_CLASS; else - nd->class=WARP_DEBUG_CLASS; + nd->class_=WARP_DEBUG_CLASS; nd->speed=200; nd->option = 0; nd->opt1 = 0; @@ -1449,11 +1539,9 @@ int npc_parse_warp(char *w1,char *w2,char *w3,char *w4) for(i=0;i<ys;i++) { for(j=0;j<xs;j++) { - int t; - t=map_getcell(m,x-xs/2+j,y-ys/2+i); - if (t==1 || t==5) + if(map_getcell(m,x-xs/2+j,y-ys/2+i,CELL_CHKNOPASS)) continue; - map_setcell(m,x-xs/2+j,y-ys/2+i,t|0x80); + map_setcell(m,x-xs/2+j,y-ys/2+i,CELL_SETNPC); } } @@ -1494,20 +1582,26 @@ static int npc_parse_shop(char *w1,char *w2,char *w3,char *w4) while (p && pos < max) { int nameid,value; + struct item_data *id; p++; if (sscanf(p, "%d:%d", &nameid, &value) != 2) break; nd->u.shop_item[pos].nameid = nameid; - if (value < 0) { - struct item_data *id = itemdb_search(nameid); + id = itemdb_search(nameid); + if (value < 0) value = id->value_buy; - } nd->u.shop_item[pos].value = value; + // check for bad prices that can possibly cause exploits + if (value*75/100 < id->value_sell*124/100) { + sprintf (tmp_output, "Item %s [%d] buying:%d < selling:%d\n", + id->name, id->nameid, value*75/100, id->value_sell*124/100); + ShowWarning (tmp_output); + } pos++; p=strchr(p,','); } if (pos == 0) { - free(nd); + aFree(nd); return 1; } nd->u.shop_item[pos++].nameid = 0; @@ -1520,14 +1614,14 @@ static int npc_parse_shop(char *w1,char *w2,char *w3,char *w4) nd->dir = dir; nd->flag = 0; memcpy(nd->name, w3, 24); - nd->class = atoi(w4); + nd->class_ = atoi(w4); nd->speed = 200; nd->chat_id = 0; nd->option = 0; nd->opt1 = 0; nd->opt2 = 0; nd->opt3 = 0; - + nd = (struct npc_data *)aRealloc(nd, sizeof(struct npc_data) + sizeof(nd->u.shop_item[0]) * pos); @@ -1554,20 +1648,28 @@ int npc_convertlabel_db(void *key,void *data,va_list ap) struct npc_label_list *lst; int num; char *p=strchr(lname,':'); - + nullpo_retr(0, ap); nullpo_retr(0, nd=va_arg(ap,struct npc_data *)); lst=nd->u.scr.label_list; num=nd->u.scr.label_list_num; if(!lst){ - lst=(struct npc_label_list *)aCalloc(1,sizeof(struct npc_label_list)); + lst=(struct npc_label_list *)aCallocA(1,sizeof(struct npc_label_list)); num=0; }else lst=(struct npc_label_list *)aRealloc(lst,sizeof(struct npc_label_list)*(num+1)); *p='\0'; - strncpy(lst[num].name,lname,24); + + // here we check if the label fit into the buffer + if (strlen(lname)>23) { + printf("npc_parse_script: label name longer than 23 chars! '%s'\n (%s)", lname, current_file); + exit(1); + } + memcpy(lst[num].name,lname,strlen(lname)+1); //including EOS + + *p=':'; lst[num].pos=pos; nd->u.scr.label_list=lst; @@ -1580,7 +1682,7 @@ int npc_convertlabel_db(void *key,void *data,va_list ap) */ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line,FILE *fp,int *lines) { - int x,y,dir=0,m,xs=0,ys=0,class=0; // [Valaris] thanks to fov + int x,y,dir=0,m,xs=0,ys=0,class_=0; // [Valaris] thanks to fov char mapname[24]; unsigned char *srcbuf=NULL,*script; int srcsize=65536; @@ -1609,94 +1711,92 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line if(strcmp(w2,"script")==0){ // ƒXƒNƒŠƒvƒg‚̉ðÍ - srcbuf=(char *)aCalloc(srcsize,sizeof(char)); + srcbuf=(unsigned char *)aCallocA(srcsize,sizeof(char)); if (strchr(first_line,'{')) { - strcpy(srcbuf,strchr(first_line,'{')); + strcpy((char *) srcbuf,strchr(first_line,'{')); startline=*lines; } else srcbuf[0]=0; while(1) { - for(i=strlen(srcbuf)-1;i>=0 && isspace(srcbuf[i]);i--); + for(i=strlen((const char *) srcbuf)-1;i>=0 && isspace(srcbuf[i]);i--); if (i>=0 && srcbuf[i]=='}') break; - fgets(line,1020,fp); + fgets((char *) line,1020,fp); (*lines)++; if (feof(fp)) break; - if (strlen(srcbuf)+strlen(line)+1>=srcsize) { + if (strlen((char *) srcbuf)+strlen((char *) line)+1>=srcsize) { srcsize += 65536; - srcbuf = (char *)aRealloc(srcbuf, srcsize); + srcbuf = (unsigned char *)aRealloc(srcbuf, srcsize); memset(srcbuf + srcsize - 65536, '\0', 65536); } if (srcbuf[0]!='{') { - if (strchr(line,'{')) { - strcpy(srcbuf,strchr(line,'{')); + if (strchr((char *) line,'{')) { + strcpy((char *) srcbuf,strchr((const char *) line,'{')); startline=*lines; } } else - strcat(srcbuf,line); + strcat((char *) srcbuf,(const char *) line); } - script=parse_script(srcbuf,startline); + script=(unsigned char *) parse_script((unsigned char *) srcbuf,startline); if (script==NULL) { // script parse error? - free(srcbuf); + aFree(srcbuf); return 1; } }else{ // duplicate‚·‚é - + char srcname[128]; struct npc_data *nd2; if( sscanf(w2,"duplicate(%[^)])",srcname)!=1 ){ - printf("bad duplicate name! : %s",w2); + printf("bad duplicate name (in %s)! : %s",current_file, w2); return 0; } if( (nd2=npc_name2id(srcname))==NULL ){ - printf("bad duplicate name! (not exist) : %s\n",srcname); + printf("bad duplicate name (in %s)! (not exist) : %s\n", current_file, srcname); return 0; } - script=nd2->u.scr.script; + script=(unsigned char *)nd2->u.scr.script; label_dup=nd2->u.scr.label_list; label_dupnum=nd2->u.scr.label_list_num; src_id=nd2->bl.id; - + }// end of ƒXƒNƒŠƒvƒg‰ðÍ nd=(struct npc_data *)aCalloc(1,sizeof(struct npc_data)); if(m==-1){ // ƒXƒNƒŠƒvƒgƒRƒs[—p‚̃_ƒ~[NPC - - }else if( sscanf(w4,"%d,%d,%d",&class,&xs,&ys)==3) { + + }else if( sscanf(w4,"%d,%d,%d",&class_,&xs,&ys)==3) { // ÚGŒ^NPC int i,j; - + if (xs>=0)xs=xs*2+1; if (ys>=0)ys=ys*2+1; - - if (class>=0) { + + if (class_>=0) { for(i=0;i<ys;i++) { for(j=0;j<xs;j++) { - int t; - t=map_getcell(m,x-xs/2+j,y-ys/2+i); - if (t==1 || t==5) + if(map_getcell(m,x-xs/2+j,y-ys/2+i,CELL_CHKNOPASS)) continue; - map_setcell(m,x-xs/2+j,y-ys/2+i,t|0x80); + map_setcell(m,x-xs/2+j,y-ys/2+i,CELL_SETNPC); } } } - + nd->u.scr.xs=xs; nd->u.scr.ys=ys; } else { // ƒNƒŠƒbƒNŒ^NPC - class=atoi(w4); + class_=atoi(w4); nd->u.scr.xs=0; nd->u.scr.ys=0; } - - if (class<0 && m>=0) { // ƒCƒxƒ“ƒgŒ^NPC + + if (class_<0 && m>=0) { // ƒCƒxƒ“ƒgŒ^NPC evflag=1; } @@ -1719,9 +1819,9 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line nd->bl.id=npc_get_new_npc_id(); nd->dir = dir; nd->flag=0; - nd->class=class; + nd->class_=class_; nd->speed=200; - nd->u.scr.script=script; + nd->u.scr.script=(char *) script; nd->u.scr.src_id=src_id; nd->chat_id=0; nd->option = 0; @@ -1730,7 +1830,7 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line nd->opt3 = 0; nd->walktimer=-1; - //printf("script npc %s %d %d read done\n",mapname,nd->bl.id,nd->class); + //printf("script npc %s %d %d read done\n",mapname,nd->bl.id,nd->class_); npc_script++; nd->bl.type=BL_NPC; nd->bl.subtype=SCRIPT; @@ -1738,6 +1838,11 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line nd->n=map_addnpc(m,nd); map_addblock(&nd->bl); + // clear event timers upon initialise + memset(nd->eventqueue, 0, sizeof(nd->eventqueue)); + for(i = 0; i < MAX_EVENTTIMER; i++) + nd->eventtimer[i] = -1; + if (evflag) { // ƒCƒxƒ“ƒgŒ^ struct event_data *ev=(struct event_data *)aCalloc(1,sizeof(struct event_data)); ev->nd=nd; @@ -1750,21 +1855,21 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line //----------------------------------------- - // ƒ‰ƒxƒ‹ƒf[ƒ^‚Ì€”õ + // ƒ‰ƒxƒ‹ƒf[ƒ^‚Ì€”õ if(srcbuf){ // script–{‘Ì‚ª‚ ‚éꇂ̈— - + // ƒ‰ƒxƒ‹ƒf[ƒ^‚̃Rƒ“ƒo[ƒg label_db=script_get_label_db(); strdb_foreach(label_db,npc_convertlabel_db,nd); - + // ‚à‚¤Žg‚í‚È‚¢‚̂Ńoƒbƒtƒ@‰ð•ú - free(srcbuf); + aFree(srcbuf); }else{ // duplicate -// nd->u.scr.label_list=malloc(sizeof(struct npc_label_list)*label_dupnum); +// nd->u.scr.label_list=aMallocA(sizeof(struct npc_label_list)*label_dupnum); // memcpy(nd->u.scr.label_list,label_dup,sizeof(struct npc_label_list)*label_dupnum); nd->u.scr.label_list=label_dup; // ƒ‰ƒxƒ‹ƒf[ƒ^‹¤—L @@ -1776,25 +1881,76 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line for(i=0;i<nd->u.scr.label_list_num;i++){ char *lname=nd->u.scr.label_list[i].name; int pos=nd->u.scr.label_list[i].pos; - + if ((lname[0]=='O' || lname[0]=='o')&&(lname[1]=='N' || lname[1]=='n')) { +/* +I rearrange the code so this is just for commenting; remove it if you have enough if it [Shinomori] struct event_data *ev; char *buf; // ƒGƒNƒXƒ|[ƒg‚³‚ê‚é ev=(struct event_data *)aCalloc(1,sizeof(struct event_data)); - buf=(char *)aCalloc(50,sizeof(char)); +why allocing 50 chars ? + buf=(char *)aCallocA(50,sizeof(char)); +why checking here? +lname is identical to nd->u.scr.label_list[i].name which is only 24 chars so check for strlen should be 23 if (strlen(lname)>24) { - printf("npc_parse_script: label name error !\n"); + printf("npc_parse_script: label name error (%s) !\n", current_file); exit(1); }else{ + //struct event_data *ev2; ev->nd=nd; ev->pos=pos; sprintf(buf,"%s::%s",nd->exname,lname); + //ev2 = strdb_search(ev_db,buf); + //if(ev2 != NULL) { + // printf("npc_parse_script : duplicate event %s\n",buf); + // aFree(ev2); + //} +you are sure reentering the same database key will overwrite the existing entry? strdb_insert(ev_db,buf,ev); +anyway instead of removing data from the db and inserting a new one +wouldn't it be easier just not to insert the new duplicate event, it is a duplicate anyway? + } +*/ + // this check is useless here because the buffer is only 24 chars + // and already overwritten if this is here is reached + // I leave the check anyway but place it correctly to npc_convertlabel_db + if (strlen(lname)>23) { + printf("npc_parse_script: label name longer than 23 chars! '%s' (%s)\n", lname, current_file); + exit(1); + }else{ + struct event_data *ev; + struct event_data *ev2; + char *buf; + // ƒGƒNƒXƒ|[ƒg‚³‚ê‚é + + // 51 comes from: 24 for npc name + 24 for label + 2 for a "::" and 1 for EOS + //buf=(char *)aMalloc(51,sizeof(char)); + // but to save some memory we alloc only the really necessary space + buf=(char *)aMalloc( (3+strlen(nd->exname)+strlen(lname))*sizeof(char)); + sprintf(buf,"%s::%s",nd->exname,lname); + + // search the label in ev_db; + // remember the label is max 50 chars + eos; see the strdb_init below + ev2 = (struct event_data *)strdb_search(ev_db,buf); + if(ev2 != NULL) { + printf("npc_parse_script : duplicate event %s (%s)\n",buf, current_file); + + // just skip the label insertion and free the alloced buffer + aFree(buf); + } + else + { // generate the data and insert it + ev=(struct event_data *)aCalloc(1,sizeof(struct event_data)); + ev->nd=nd; + ev->pos=pos; + strdb_insert(ev_db,buf,ev); + } + } } } - + //----------------------------------------- // ƒ‰ƒxƒ‹ƒf[ƒ^‚©‚çƒ^ƒCƒ}[ƒCƒxƒ“ƒgŽæ‚èž‚Ý for(i=0;i<nd->u.scr.label_list_num;i++){ @@ -1806,7 +1962,7 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line struct npc_timerevent_list *te=nd->u.scr.timer_event; int j,k=nd->u.scr.timeramount; if(te==NULL) - te=(struct npc_timerevent_list *)aCalloc(1,sizeof(struct npc_timerevent_list)); + te=(struct npc_timerevent_list *)aCallocA(1,sizeof(struct npc_timerevent_list)); else te=(struct npc_timerevent_list *)aRealloc( te, sizeof(struct npc_timerevent_list) * (k+1) ); for(j=0;j<k;j++){ @@ -1824,7 +1980,7 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line nd->u.scr.nexttimer=-1; nd->u.scr.timerid=-1; - + return 0; } @@ -1843,7 +1999,7 @@ static int npc_parse_function(char *w1,char *w2,char *w3,char *w4,char *first_li char *p; // ƒXƒNƒŠƒvƒg‚̉ðÍ - srcbuf=(char *)aCalloc(srcsize,sizeof(char)); + srcbuf=(char *)aCallocA(srcsize,sizeof(char)); if (strchr(first_line,'{')) { strcpy(srcbuf,strchr(first_line,'{')); startline=*lines; @@ -1870,14 +2026,14 @@ static int npc_parse_function(char *w1,char *w2,char *w3,char *w4,char *first_li } else strcat(srcbuf,line); } - script=parse_script(srcbuf,startline); + script= parse_script((unsigned char *) srcbuf,startline); if (script==NULL) { // script parse error? - free(srcbuf); + aFree(srcbuf); return 1; } - p=(char *)aCalloc(50,sizeof(char)); + p=(char *)aCallocA(50,sizeof(char)); strncpy(p,w3,50); strdb_insert(script_get_userfunc_db(),p,script); @@ -1885,10 +2041,10 @@ static int npc_parse_function(char *w1,char *w2,char *w3,char *w4,char *first_li // label_db=script_get_label_db(); // ‚à‚¤Žg‚í‚È‚¢‚̂Ńoƒbƒtƒ@‰ð•ú - free(srcbuf); - + aFree(srcbuf); + // printf("function %s => %p\n",p,script); - + return 0; } @@ -1899,7 +2055,7 @@ static int npc_parse_function(char *w1,char *w2,char *w3,char *w4,char *first_li */ int npc_parse_mob(char *w1,char *w2,char *w3,char *w4) { - int m,x,y,xs,ys,class,num,delay1,delay2,level; + int m,x,y,xs,ys,class_,num,delay1,delay2,level; int i; char mapname[24]; char mobname[24]; @@ -1910,7 +2066,7 @@ int npc_parse_mob(char *w1,char *w2,char *w3,char *w4) delay1=delay2=0; // ˆø”‚̌”ƒ`ƒFƒbƒN if (sscanf(w1,"%[^,],%d,%d,%d,%d",mapname,&x,&y,&xs,&ys) < 3 || - sscanf(w4,"%d,%d,%d,%d,%s",&class,&num,&delay1,&delay2,eventname) < 2 ) { + sscanf(w4,"%d,%d,%d,%d,%s",&class_,&num,&delay1,&delay2,eventname) < 2 ) { printf("bad monster line : %s\n",w3); return 1; } @@ -1925,13 +2081,13 @@ int npc_parse_mob(char *w1,char *w2,char *w3,char *w4) for(i=0;i<num;i++) { md=(struct mob_data *)aCalloc(1,sizeof(struct mob_data)); - if(class>4000) { // large/tiny mobs [Valaris] + if(class_>4000) { // large/tiny mobs [Valaris] md->size=2; - class-=4000; + class_-=4000; } - else if(class>2000) { + else if(class_>2000) { md->size=1; - class-=2000; + class_-=2000; } md->bl.prev=NULL; @@ -1940,19 +2096,16 @@ int npc_parse_mob(char *w1,char *w2,char *w3,char *w4) md->bl.x=x; md->bl.y=y; - if(sscanf(w3,"%[^,],%d",mobname,&level) > 1) { - if(strcmp(mobname,"--en--")==0) - memcpy(md->name,mob_db[class].name,24); - else if(strcmp(mobname,"--ja--")==0) - memcpy(md->name,mob_db[class].jname,24); + if(sscanf(w3,"%[^,],%d",mobname,&level) > 1) md->level=level; - } - - else - memcpy(md->name,w3,24); + if(strcmp(mobname,"--en--")==0) + memcpy(md->name,mob_db[class_].name,24); + else if(strcmp(mobname,"--ja--")==0) + memcpy(md->name,mob_db[class_].jname,24); + else memcpy(md->name,mobname,24); md->n = i; - md->base_class = md->class = class; + md->base_class = md->class_ = class_; md->bl.id=npc_get_new_npc_id(); md->m =m; md->x0=x; @@ -1966,9 +2119,9 @@ int npc_parse_mob(char *w1,char *w2,char *w3,char *w4) md->timer = -1; md->target_id=0; md->attacked_id=0; - md->speed=mob_db[class].speed; + md->speed=mob_db[class_].speed; - if (mob_db[class].mode&0x02) + if (mob_db[class_].mode&0x02) md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item)); else md->lootitem=NULL; @@ -2013,7 +2166,7 @@ static int npc_parse_mapflag(char *w1,char *w2,char *w3,char *w4) //ƒ}ƒbƒvƒtƒ‰ƒO if ( strcmpi(w3,"nosave")==0) { if (strcmp(w4,"SavePoint")==0) { - memcpy(map[m].save.map,"SavePoint",16); + memcpy(map[m].save.map,"SavePoint",10); map[m].save.x=-1; map[m].save.y=-1; }else if (sscanf(w4,"%[^,],%d,%d",savemap,&savex,&savey)==3) { @@ -2106,19 +2259,19 @@ static int npc_parse_mapflag(char *w1,char *w2,char *w3,char *w4) } else if (strcmpi(w3,"noicewall")==0) { // noicewall [Valaris] map[m].flag.noicewall=1; - } + } else if (strcmpi(w3,"snow")==0) { // snow [Valaris] map[m].flag.snow=1; - } + } else if (strcmpi(w3,"fog")==0) { // fog [Valaris] map[m].flag.fog=1; - } + } else if (strcmpi(w3,"sakura")==0) { // sakura [Valaris] map[m].flag.sakura=1; - } + } else if (strcmpi(w3,"leaves")==0) { // leaves [Valaris] map[m].flag.leaves=1; - } + } else if (strcmpi(w3,"rain")==0) { // rain [Valaris] map[m].flag.rain=1; } @@ -2128,15 +2281,116 @@ static int npc_parse_mapflag(char *w1,char *w2,char *w3,char *w4) else if (strcmpi(w3,"nogo")==0) { // celest map[m].flag.nogo=1; } - + + return 0; +} + +void npc_parsesrcfile(char *name) +{ + int m, lines = 0; + char line[1024]; + + FILE *fp = fopen (name,"r"); + if (fp == NULL) { + ShowError ("File not found : %s\n", name); + exit(1); + } + current_file = name; + + while (fgets(line, 1020, fp)) { + char w1[1024], w2[1024], w3[1024], w4[1024], mapname[1024]; + int i, j, w4pos, count; + lines++; + + if (line[0] == '/' && line[1] == '/') + continue; + // •s—v‚ȃXƒy[ƒX‚âƒ^ƒu‚̘A‘±‚Í‹l‚ß‚é + for (i = j = 0; line[i]; i++) { + if (line[i]==' ') { + if (!((line[i+1] && (isspace(line[i+1]) || line[i+1]==',')) || + (j && line[j-1]==','))) + line[j++]=' '; + } else if (line[i]=='\t') { + if (!(j && line[j-1]=='\t')) + line[j++]='\t'; + } else + line[j++]=line[i]; + } + // ʼn‚̓^ƒu‹æØ‚è‚Ń`ƒFƒbƒN‚µ‚Ă݂ÄAƒ_ƒ‚È‚çƒXƒy[ƒX‹æØ‚è‚ÅŠm”F + if ((count = sscanf(line,"%[^\t]\t%[^\t]\t%[^\t\r\n]\t%n%[^\t\r\n]", w1, w2, w3, &w4pos, w4)) < 3 && + (count = sscanf(line,"%s%s%s%n%s", w1, w2, w3, &w4pos, w4)) < 3) { + continue; + } + // ƒ}ƒbƒv‚Ì‘¶ÝŠm”F + if (strcmp(w1,"-") !=0 && strcmpi(w1,"function") != 0 ){ + sscanf(w1,"%[^,]",mapname); + m = map_mapname2mapid(mapname); + if (strlen(mapname)>16 || m<0) { + // "mapname" is not assigned to this server + continue; + } + } + if (strcmpi(w2,"warp") == 0 && count > 3) { + npc_parse_warp(w1,w2,w3,w4); + } else if (strcmpi(w2,"shop") == 0 && count > 3) { + npc_parse_shop(w1,w2,w3,w4); + } else if (strcmpi(w2,"script") == 0 && count > 3) { + if (strcmpi(w1,"function") == 0) { + npc_parse_function(w1,w2,w3,w4,line+w4pos,fp,&lines); + } else { + npc_parse_script(w1,w2,w3,w4,line+w4pos,fp,&lines); + } + } else if ((i = 0, sscanf(w2,"duplicate%n",&i), (i > 0 && w2[i] == '(')) && count > 3) { + npc_parse_script(w1,w2,w3,w4,line+w4pos,fp,&lines); + } else if (strcmpi(w2,"monster") == 0 && count > 3) { + npc_parse_mob(w1,w2,w3,w4); + } else if (strcmpi(w2,"mapflag") == 0 && count >= 3) { + npc_parse_mapflag(w1,w2,w3,w4); + } + } + fclose(fp); + + return; +} + +static int npc_read_indoors(void) +{ + char *buf,*p; + int s, m; + + buf=(char *) grfio_reads("data\\indoorrswtable.txt",&s); + + if(buf==NULL) + return -1; + + buf[s]=0; + for(p=buf;p-buf<s;){ + char buf2[64]; + + if(sscanf(p,"%[^#]#",buf2) == 1){ + char map_name[64] = ""; + strncpy(map_name, buf2, strlen(buf2) - 4); + strcat(map_name, ".gat"); + if ((m = map_mapname2mapid(map_name)) >= 0) + map[m].flag.indoors=1; + } + + p=strchr(p,10); + if(!p) break; + p++; + } + aFree(buf); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\indoorrswtable.txt"); + ShowStatus(tmp_output); + return 0; } static int ev_db_final(void *key,void *data,va_list ap) { - free(data); - if(strstr(key,"::")!=NULL) - free(key); + aFree(data); + if(strstr((const char *) key,"::")!=NULL) + aFree(key); return 0; } static int npcname_db_final(void *key,void *data,va_list ap) @@ -2144,6 +2398,75 @@ static int npcname_db_final(void *key,void *data,va_list ap) return 0; } /*========================================== + * + *------------------------------------------ + */ +int npc_cleanup_sub (struct block_list *bl, va_list ap) { + nullpo_retr(0, bl); + + switch(bl->type) { + case BL_NPC: + npc_unload((struct npc_data *)bl); + break; + case BL_MOB: + mob_unload((struct mob_data *)bl); + break; + } + + return 0; +} +int npc_reload(void) +{ + struct npc_src_list *nsl; + int m, last_npc_id; + time_t last_time = time(0); + int busy = 0; + char c = '-'; + + for (m = 0; m < map_num; m++) { + map_foreachinarea(npc_cleanup_sub, m, 0, 0, map[m].xs, map[m].ys, 0); + map[m].npc_num = 0; + } + if(ev_db) + strdb_final(ev_db,ev_db_final); + if(npcname_db) + strdb_final(npcname_db,npcname_db_final); + + // anything else we should cleanup? + // Reloading npc's now + ev_db = strdb_init(51); + npcname_db = strdb_init(24); + ev_db->release = ev_release; + npc_warp = npc_shop = npc_script = npc_mob = 0; + last_npc_id = npc_id; + + for (nsl = npc_src_first; nsl; nsl = nsl->next) { + npc_parsesrcfile(nsl->name); + printf("\r"); + ShowStatus("Loading NPCs... Working: "); + if (last_time != time(0)) { + last_time = time(0); + switch(busy) { + case 0: c='\\'; busy++; break; + case 1: c='|'; busy++; break; + case 2: c='/'; busy++; break; + case 3: c='-'; busy=0; + } + } + printf("[%c]",c); + fflush(stdout); + } + printf("\r"); + ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:%30s\n\t-'" + CL_WHITE"%d"CL_RESET"' Warps\n\t-'" + CL_WHITE"%d"CL_RESET"' Shops\n\t-'" + CL_WHITE"%d"CL_RESET"' Scripts\n\t-'" + CL_WHITE"%d"CL_RESET"' Mobs\n", + npc_id - last_npc_id, "", npc_warp, npc_shop, npc_script, npc_mob); + + return 0; +} +/*========================================== * I—¹ *------------------------------------------ */ @@ -2153,7 +2476,6 @@ int do_final_npc(void) struct block_list *bl; struct npc_data *nd; struct mob_data *md; - struct chat_data *cd; struct pet_data *pd; if(ev_db) @@ -2161,53 +2483,27 @@ int do_final_npc(void) if(npcname_db) strdb_final(npcname_db,npcname_db_final); - for(i=START_NPC_NUM;i<npc_id;i++){ - if((bl=map_id2bl(i))){ + npc_clearsrcfile(); + + for (i = START_NPC_NUM; i < npc_id; i++){ + if((bl = map_id2bl(i))){ if(bl->type == BL_NPC && (nd = (struct npc_data *)bl)){ - if(nd->chat_id && (cd=(struct chat_data*)map_id2bl(nd->chat_id))){ - free(cd); - cd = NULL; - } - if(nd->bl.subtype == SCRIPT){ - if(nd->u.scr.timer_event) - free(nd->u.scr.timer_event); - if(nd->u.scr.src_id==0){ - if(nd->u.scr.script){ - free(nd->u.scr.script); - nd->u.scr.script=NULL; - } - if(nd->u.scr.label_list){ - free(nd->u.scr.label_list); - nd->u.scr.label_list = NULL; - } - } - } - free(nd); - nd = NULL; - }else if(bl->type == BL_MOB && (md = (struct mob_data *)bl)){ - if(md->lootitem){ - free(md->lootitem); + npc_unload(nd); + }else if (bl->type == BL_MOB && (md = (struct mob_data *)bl)){ + if (md->lootitem){ + aFree(md->lootitem); md->lootitem = NULL; } - free(md); + aFree(md); md = NULL; }else if(bl->type == BL_PET && (pd = (struct pet_data *)bl)){ - free(pd); + aFree(pd); pd = NULL; } } } - - return 0; -} - -void ev_release(struct dbn *db, int which) -{ - if (which & 0x1) - free(db->key); - if (which & 0x2) - free(db->data); + return 0; } /*========================================== @@ -2217,86 +2513,56 @@ void ev_release(struct dbn *db, int which) int do_init_npc(void) { struct npc_src_list *nsl; - FILE *fp; - char line[1024]; - int m,lines; - - ev_db=strdb_init(24); - npcname_db=strdb_init(24); - - ev_db->release = ev_release; - - memset(&ev_tm_b,-1,sizeof(ev_tm_b)); - - for(nsl=npc_src_first;nsl;nsl=nsl->next) { - if(nsl->prev){ - free(nsl->prev); + time_t last_time = time(0); + int busy = 0; + char c = '-'; + + // indoorrswtable.txt and etcinfo.txt [Celest] + if (battle_config.indoors_override_grffile) + npc_read_indoors(); + //npc_read_weather(); + + // comparing only the first 24 chars of labels that are 50 chars long isn't that nice + // will cause "duplicated" labels where actually no dup is... + //ev_db=strdb_init(24); + ev_db = strdb_init(51); + npcname_db = strdb_init(24); + ev_db->release = ev_release; + + memset(&ev_tm_b, -1, sizeof(ev_tm_b)); + + for (nsl = npc_src_first; nsl; nsl = nsl->next) { + /*if(nsl->prev){ // [Shinomori] + aFree(nsl->prev); nsl->prev = NULL; - } - fp=fopen(nsl->name,"r"); - if (fp==NULL) { - printf("file not found : %s\n",nsl->name); - exit(1); - } - lines=0; - while(fgets(line,1020,fp)) { - char w1[1024],w2[1024],w3[1024],w4[1024],mapname[1024]; - int i,j,w4pos,count; - lines++; - - if (line[0] == '/' && line[1] == '/') - continue; - // •s—v‚ȃXƒy[ƒX‚âƒ^ƒu‚̘A‘±‚Í‹l‚ß‚é - for(i=j=0;line[i];i++) { - if (line[i]==' ') { - if (!((line[i+1] && (isspace(line[i+1]) || line[i+1]==',')) || - (j && line[j-1]==','))) - line[j++]=' '; - } else if (line[i]=='\t') { - if (!(j && line[j-1]=='\t')) - line[j++]='\t'; - } else - line[j++]=line[i]; - } - // ʼn‚̓^ƒu‹æØ‚è‚Ń`ƒFƒbƒN‚µ‚Ă݂ÄAƒ_ƒ‚È‚çƒXƒy[ƒX‹æØ‚è‚ÅŠm”F - if ((count=sscanf(line,"%[^\t]\t%[^\t]\t%[^\t\r\n]\t%n%[^\t\r\n]",w1,w2,w3,&w4pos,w4)) < 3 && - (count=sscanf(line,"%s%s%s%n%s",w1,w2,w3,&w4pos,w4)) < 3) { - continue; - } - // ƒ}ƒbƒv‚Ì‘¶ÝŠm”F - if( strcmp(w1,"-")!=0 && strcmpi(w1,"function")!=0 ){ - sscanf(w1,"%[^,]",mapname); - m = map_mapname2mapid(mapname); - if (strlen(mapname)>16 || m<0) { - // "mapname" is not assigned to this server - continue; - } - } - if (strcmpi(w2,"warp")==0 && count > 3) { - npc_parse_warp(w1,w2,w3,w4); - } else if (strcmpi(w2,"shop")==0 && count > 3) { - npc_parse_shop(w1,w2,w3,w4); - } else if (strcmpi(w2,"script")==0 && count > 3) { - if( strcmpi(w1,"function")==0 ){ - npc_parse_function(w1,w2,w3,w4,line+w4pos,fp,&lines); - }else{ - npc_parse_script(w1,w2,w3,w4,line+w4pos,fp,&lines); - } - } else if ( (i=0,sscanf(w2,"duplicate%n",&i), (i>0 && w2[i]=='(')) && count > 3) { - npc_parse_script(w1,w2,w3,w4,line+w4pos,fp,&lines); - } else if (strcmpi(w2,"monster")==0 && count > 3) { - npc_parse_mob(w1,w2,w3,w4); - } else if (strcmpi(w2,"mapflag")==0 && count >= 3) { - npc_parse_mapflag(w1,w2,w3,w4); + }*/ + // + npc_parsesrcfile(nsl->name); + current_file = NULL; + printf("\r"); + ShowStatus("Loading NPCs... Working: "); + if (last_time != time(0)) { + last_time = time(0); + switch(busy) { + case 0: c='\\'; busy++; break; + case 1: c='|'; busy++; break; + case 2: c='/'; busy++; break; + case 3: c='-'; busy=0; } } - fclose(fp); + printf("[%c]",c); + fflush(stdout); // printf("\rLoading NPCs [%d]: %-54s",npc_id-START_NPC_NUM,nsl->name); // fflush(stdout); } - printf("\rNPCs Loaded: %d [Warps:%d Shops:%d Scripts:%d Mobs:%d]\n", - npc_id-START_NPC_NUM,npc_warp,npc_shop,npc_script,npc_mob); - + printf("\r"); + ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:%30s\n\t-'" + CL_WHITE"%d"CL_RESET"' Warps\n\t-'" + CL_WHITE"%d"CL_RESET"' Shops\n\t-'" + CL_WHITE"%d"CL_RESET"' Scripts\n\t-'" + CL_WHITE"%d"CL_RESET"' Mobs\n", + npc_id - START_NPC_NUM, "", npc_warp, npc_shop, npc_script, npc_mob); + add_timer_func_list(npc_walktimer,"npc_walktimer"); // [Valaris] add_timer_func_list(npc_event_timer,"npc_event_timer"); add_timer_func_list(npc_event_do_clock,"npc_event_do_clock"); diff --git a/src/map/npc.h b/src/map/npc.h index 4f0c43cba..2f81345d7 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -8,6 +8,10 @@ #define WARP_DEBUG_CLASS 722 #define INVISIBLE_CLASS 32767 +#ifdef PCRE_SUPPORT +void npc_chat_finalize(struct npc_data *nd); +#endif +int npc_chat_sub(struct block_list *bl, va_list ap); int npc_event_dequeue(struct map_session_data *sd); int npc_event_timer(int tid,unsigned int tick,int id,int data); int npc_event(struct map_session_data *sd,const char *npcname,int); @@ -22,6 +26,7 @@ int npc_buylist(struct map_session_data *,int,unsigned short *); int npc_selllist(struct map_session_data *,int,unsigned short *); int npc_parse_mob(char *w1,char *w2,char *w3,char *w4); int npc_parse_warp(char *w1,char *w2,char *w3,char *w4); +int npc_globalmessage(const char *name,char *mes); int npc_enable(const char *name,int flag); struct npc_data* npc_name2id(const char *name); @@ -37,16 +42,21 @@ void npc_delsrcfile(char *); int do_final_npc(void); int do_init_npc(void); int npc_event_do_oninit(void); -int npc_do_ontimer(int,struct map_session_data *,int); +int npc_do_ontimer(int,int); int npc_event_doall(const char *name); int npc_event_do(const char *name); +int npc_event_doall_id(const char *name, int id); -int npc_timerevent_start(struct npc_data *nd); +int npc_timerevent_start(struct npc_data *nd, int rid); int npc_timerevent_stop(struct npc_data *nd); int npc_gettimerevent_tick(struct npc_data *nd); int npc_settimerevent_tick(struct npc_data *nd,int newtimer); -int npc_delete(struct npc_data *nd); +int npc_remove_map(struct npc_data *nd); +int npc_unload(struct npc_data *nd); +int npc_reload(void); + +extern char *current_file; #endif diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c new file mode 100644 index 000000000..5ec8540ae --- /dev/null +++ b/src/map/npc_chat.c @@ -0,0 +1,502 @@ +#ifdef PCRE_SUPPORT + +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#ifdef __WIN32 +#define __USE_W32_SOCKETS +#include <windows.h> +#else +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#endif +#include <time.h> + +#include "../common/timer.h" +#include "../common/malloc.h" +#include "../common/version.h" +#include "../common/nullpo.h" +#include "../common/showmsg.h" + +#include "map.h" +#include "status.h" +#include "npc.h" +#include "chat.h" +#include "script.h" +#include "battle.h" + +#include "pcre.h" + +/** + * Written by MouseJstr in a vision... (2/21/2005) + * + * This allows you to make npc listen for spoken text (global + * messages) and pattern match against that spoken text using perl + * regular expressions. + * + * Please feel free to copy this code into your own personal ragnarok + * servers or distributions but please leave my name. Also, please + * wait until I've put it into the main eA branch which means I + * believe it is ready for distribution. + * + * So, how do people use this? + * + * The first and most important function is defpattern + * + * defpattern 1, "[^:]+: (.*) loves (.*)", "label"; + * + * this defines a new pattern in set 1 using perl syntax + * (http://www.troubleshooters.com/codecorn/littperl/perlreg.htm) + * and tells it to jump to the supplied label when the pattern + * is matched. + * + * each of the matched Groups will result in a variable being + * set ($p1$ through $p9$ with $p0$ being the entire string) + * before the script gets executed. + * + * activatepset 1; + * + * This activates a set of patterns.. You can have many pattern + * sets defined and many active all at once. This feature allows + * you to set up "conversations" and ever changing expectations of + * the pattern matcher + * + * deactivatepset 1; + * + * turns off a pattern set; + * + * deactivatepset -1; + * + * turns off ALL pattern sets; + * + * deletepset 1; + * + * deletes a pset + */ + +/* Structure containing all info associated with a single pattern + block */ + +struct pcrematch_entry { + struct pcrematch_entry *next_; + char *pattern_; + pcre *pcre_; + pcre_extra *pcre_extra_; + char *label_; +}; + +/* A set of patterns that can be activated and deactived with a single + command */ + +struct pcrematch_set { + struct pcrematch_set *next_, *prev_; + struct pcrematch_entry *head_; + int setid_; +}; + +/* + * Entire data structure hung off a NPC + * + * The reason I have done it this way (a void * in npc_data and then + * this) was to reduce the number of patches that needed to be applied + * to a ragnarok distribution to bring this code online. I + * also wanted people to be able to grab this one file to get updates + * without having to do a large number of changes. + */ + +struct npc_parse { + struct pcrematch_set *active_; + struct pcrematch_set *inactive_; +}; + + +/** + * delete everythign associated with a entry + * + * This does NOT do the list management + */ + +void finalize_pcrematch_entry(struct pcrematch_entry *e) { + free(e->pcre_); + free(e->pcre_extra_); + aFree(e->pattern_); + aFree(e->label_); +} + +/** + * Lookup (and possibly create) a new set of patterns by the set id + */ +static struct pcrematch_set * lookup_pcreset(struct npc_data *nd,int setid) +{ + struct pcrematch_set *pcreset; + struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; + if (npcParse == NULL) + nd->chatdb = npcParse = (struct npc_parse *) + aCalloc(sizeof(struct npc_parse), 1); + + pcreset = npcParse->active_; + + while (pcreset != NULL) { + if (pcreset->setid_ == setid) + break; + pcreset = pcreset->next_; + } + if (pcreset == NULL) + pcreset = npcParse->inactive_; + + while (pcreset != NULL) { + if (pcreset->setid_ == setid) + break; + pcreset = pcreset->next_; + } + + if (pcreset == NULL) { + pcreset = (struct pcrematch_set *) + aCalloc(sizeof(struct pcrematch_set), 1); + pcreset->next_ = npcParse->inactive_; + if (pcreset->next_ != NULL) + pcreset->next_->prev_ = pcreset; + pcreset->prev_ = 0; + npcParse->inactive_ = pcreset; + pcreset->setid_ = setid; + } + + return pcreset; +} + +/** + * activate a set of patterns. + * + * if the setid does not exist, this will silently return + */ + +static void activate_pcreset(struct npc_data *nd,int setid) { + struct pcrematch_set *pcreset; + struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; + if (npcParse == NULL) + return; // Nothing to activate... + pcreset = npcParse->inactive_; + while (pcreset != NULL) { + if (pcreset->setid_ == setid) + break; + pcreset = pcreset->next_; + } + if (pcreset == NULL) + return; // not in inactive list + if (pcreset->next_ != NULL) + pcreset->next_->prev_ = pcreset->prev_; + if (pcreset->prev_ != NULL) + pcreset->prev_->next_ = pcreset->next_; + else + npcParse->inactive_ = pcreset->next_; + + pcreset->prev_ = NULL; + pcreset->next_ = npcParse->active_; + if (pcreset->next_ != NULL) + pcreset->next_->prev_ = pcreset; + npcParse->active_ = pcreset; +} + +/** + * deactivate a set of patterns. + * + * if the setid does not exist, this will silently return + */ + +static void deactivate_pcreset(struct npc_data *nd,int setid) { + struct pcrematch_set *pcreset; + struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; + if (npcParse == NULL) + return; // Nothing to deactivate... + if (setid == -1) { + while(npcParse->active_ != NULL) + deactivate_pcreset(nd, npcParse->active_->setid_); + return; + } + pcreset = npcParse->active_; + while (pcreset != NULL) { + if (pcreset->setid_ == setid) + break; + pcreset = pcreset->next_; + } + if (pcreset == NULL) + return; // not in active list + if (pcreset->next_ != NULL) + pcreset->next_->prev_ = pcreset->prev_; + if (pcreset->prev_ != NULL) + pcreset->prev_->next_ = pcreset->next_; + else + npcParse->active_ = pcreset->next_; + + pcreset->prev_ = NULL; + pcreset->next_ = npcParse->inactive_; + if (pcreset->next_ != NULL) + pcreset->next_->prev_ = pcreset; + npcParse->inactive_ = pcreset; +} + +/** + * delete a set of patterns. + */ +static void delete_pcreset(struct npc_data *nd,int setid) { + int active = 1; + struct pcrematch_set *pcreset; + struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; + if (npcParse == NULL) + return; // Nothing to deactivate... + pcreset = npcParse->active_; + while (pcreset != NULL) { + if (pcreset->setid_ == setid) + break; + pcreset = pcreset->next_; + } + if (pcreset == NULL) { + active = 0; + pcreset = npcParse->inactive_; + while (pcreset != NULL) { + if (pcreset->setid_ == setid) + break; + pcreset = pcreset->next_; + } + } + if (pcreset == NULL) + return; + + if (pcreset->next_ != NULL) + pcreset->next_->prev_ = pcreset->prev_; + if (pcreset->prev_ != NULL) + pcreset->prev_->next_ = pcreset->next_; + else if(active == 1) + npcParse->active_ = pcreset->next_; + else + npcParse->inactive_ = pcreset->next_; + + pcreset->prev_ = NULL; + pcreset->next_ = NULL; + + while (pcreset->head_) { + struct pcrematch_entry *n = pcreset->head_->next_;; + finalize_pcrematch_entry(pcreset->head_); + pcreset->head_ = n; + } + + aFree(pcreset); +} + +/** + * create a new pattern entry + */ +static struct pcrematch_entry *create_pcrematch_entry(struct pcrematch_set * set) { + struct pcrematch_entry * e = (struct pcrematch_entry *) + aCalloc(sizeof(struct pcrematch_entry), 1); + struct pcrematch_entry * last = set->head_; + + // Normally we would have just stuck it at the end of the list but + // this doesn't sink up with peoples usage pattern. They wanted + // the items defined first to have a higher priority then the + // items defined later.. as a result, we have to do some work up + // front.. + + /* if we are the first pattern, stick us at the end */ + if (last == NULL) { + set->head_ = e; + return e; + } + + /* Look for the last entry */ + while (last->next_ != NULL) + last = last->next_; + + last->next_ = e; + e->next_ = NULL; + + return e; +} + +/** + * define/compile a new pattern + */ + +void npc_chat_def_pattern(struct npc_data *nd, int setid, + const char *pattern, const char *label) +{ + const char *err; + int erroff; + + struct pcrematch_set * s = lookup_pcreset(nd, setid); + struct pcrematch_entry *e = create_pcrematch_entry(s); + e->pattern_ = aStrdup(pattern); + e->label_ = aStrdup(label); + e->pcre_ = pcre_compile(pattern, PCRE_CASELESS, &err, &erroff, NULL); + e->pcre_extra_ = pcre_study(e->pcre_, 0, &err); +} + +/** + * Delete everything associated with a NPC concerning the pattern + * matching code + * + * this could be more efficent but.. how often do you do this? + */ +void npc_chat_finalize(struct npc_data *nd) +{ + struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; + if (npcParse == NULL) + return; + + while(npcParse->active_) + delete_pcreset(nd, npcParse->active_->setid_); + + while(npcParse->inactive_) + delete_pcreset(nd, npcParse->inactive_->setid_); +} + +/** + * Handler called whenever a global message is spoken in a NPC's area + */ +int npc_chat_sub(struct block_list *bl, va_list ap) +{ + struct npc_data *nd = (struct npc_data *)bl; + struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; + unsigned char *msg; + int len, pos, i; + struct map_session_data *sd; + struct npc_label_list *lst; + struct pcrematch_set *pcreset; + + // Not interested in anything you might have to say... + if (npcParse == NULL || npcParse->active_ == NULL) + return 0; + + msg = va_arg(ap,unsigned char*); + len = va_arg(ap,int); + sd = va_arg(ap,struct map_session_data *); + + // grab the active list + pcreset = npcParse->active_; + + // interate across all active sets + while (pcreset != NULL) { + struct pcrematch_entry *e = pcreset->head_; + // interate across all patterns in that set + while (e != NULL) { + int offsets[20]; + char buf[255]; + // perform pattern match + int r = pcre_exec(e->pcre_, e->pcre_extra_, msg, len, 0, + 0, offsets, sizeof(offsets) / sizeof(offsets[0])); + if (r >= 0) { + // save out the matched strings + switch (r) { + case 10: + memcpy(buf, &msg[offsets[18]], offsets[19]); + buf[offsets[19]] = '\0'; + set_var(sd, "$p9$", buf); + case 9: + memcpy(buf, &msg[offsets[16]], offsets[17]); + buf[offsets[17]] = '\0'; + set_var(sd, "$p8$", buf); + case 8: + memcpy(buf, &msg[offsets[14]], offsets[15]); + buf[offsets[15]] = '\0'; + set_var(sd, "$p7$", buf); + case 7: + memcpy(buf, &msg[offsets[12]], offsets[13]); + buf[offsets[13]] = '\0'; + set_var(sd, "$p6$", buf); + case 6: + memcpy(buf, &msg[offsets[10]], offsets[11]); + buf[offsets[11]] = '\0'; + set_var(sd, "$p5$", buf); + case 5: + memcpy(buf, &msg[offsets[8]], offsets[9]); + buf[offsets[9]] = '\0'; + set_var(sd, "$p4$", buf); + case 4: + memcpy(buf, &msg[offsets[6]], offsets[7]); + buf[offsets[7]] = '\0'; + set_var(sd, "$p3$", buf); + case 3: + memcpy(buf, &msg[offsets[4]], offsets[5]); + buf[offsets[5]] = '\0'; + set_var(sd, "$p2$", buf); + case 2: + memcpy(buf, &msg[offsets[2]], offsets[3]); + buf[offsets[3]] = '\0'; + set_var(sd, "$p1$", buf); + case 1: + memcpy(buf, &msg[offsets[0]], offsets[1]); + buf[offsets[1]] = '\0'; + set_var(sd, "$p0$", buf); + } + + // find the target label.. this sucks.. + lst=nd->u.scr.label_list; + pos = -1; + for (i = 0; i < nd->u.scr.label_list_num; i++) { + if (strncmp(lst[i].name, e->label_, sizeof(lst[i].name)) == 0) { + pos = lst[i].pos; + break; + } + } + if (pos == -1) { + printf("Unable to find label: %s", e->label_); + // unable to find label... do something.. + return 0; + } + // run the npc script + run_script(nd->u.scr.script,pos,sd->bl.id,nd->bl.id); + return 0; + } + e = e->next_; + } + pcreset = pcreset->next_; + } + + return 0; +} + +// Various script builtins used to support these functions + +int buildin_defpattern(struct script_state *st) { + int setid=conv_num(st,& (st->stack->stack_data[st->start+2])); + char *pattern=conv_str(st,& (st->stack->stack_data[st->start+3])); + char *label=conv_str(st,& (st->stack->stack_data[st->start+4])); + struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); + + npc_chat_def_pattern(nd, setid, pattern, label); + + return 0; +} + +int buildin_activatepset(struct script_state *st) { + int setid=conv_num(st,& (st->stack->stack_data[st->start+2])); + struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); + + activate_pcreset(nd, setid); + + return 0; +} +int buildin_deactivatepset(struct script_state *st) { + int setid=conv_num(st,& (st->stack->stack_data[st->start+2])); + struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); + + deactivate_pcreset(nd, setid); + + return 0; +} +int buildin_deletepset(struct script_state *st) { + int setid=conv_num(st,& (st->stack->stack_data[st->start+2])); + struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); + + delete_pcreset(nd, setid); + + return 0; +} + + +#endif diff --git a/src/map/party.c b/src/map/party.c index 82b77cf6b..7eb3f02dc 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -30,7 +30,7 @@ int party_send_xyhp_timer(int tid,unsigned int tick,int id,int data); */ static int party_db_final(void *key,void *data,va_list ap) { - free(data); + aFree(data); return 0; } void do_final_party(void) @@ -49,7 +49,7 @@ void do_init_party(void) // ŒŸõ struct party *party_search(int party_id) { - return numdb_search(party_db,party_id); + return (struct party *) numdb_search(party_db,party_id); } int party_searchname_sub(void *key,void *data,va_list ap) { @@ -69,12 +69,12 @@ struct party* party_searchname(char *str) return p; } // 쬗v‹ -int party_create(struct map_session_data *sd,char *name) +int party_create(struct map_session_data *sd,char *name,int item,int item2) { nullpo_retr(0, sd); if(sd->status.party_id==0) - intif_create_party(sd,name); + intif_create_party(sd,name,item,item2); else clif_party_created(sd,2); return 0; @@ -91,7 +91,7 @@ int party_created(int account_id,int fail,int party_id,char *name) if(fail==0){ struct party *p; sd->status.party_id=party_id; - if((p=numdb_search(party_db,party_id))!=NULL){ + if((p=(struct party *) numdb_search(party_db,party_id))!=NULL){ printf("party: id already exists!\n"); exit(1); } @@ -121,7 +121,7 @@ int party_check_member(struct party *p) nullpo_retr(0, p); for(i=0;i<fd_max;i++){ - if(session[i] && (sd=session[i]->session_data) && sd->state.auth){ + if(session[i] && (sd=(struct map_session_data *) session[i]->session_data) && sd->state.auth){ if(sd->status.party_id==p->party_id){ int j,f=1; for(j=0;j<MAX_PARTY;j++){ // ƒp[ƒeƒB‚Ƀf[ƒ^‚ª‚ ‚é‚©Šm”F @@ -149,7 +149,7 @@ int party_recv_noinfo(int party_id) int i; struct map_session_data *sd; for(i=0;i<fd_max;i++){ - if(session[i] && (sd=session[i]->session_data) && sd->state.auth){ + if(session[i] && (sd=(struct map_session_data *) session[i]->session_data) && sd->state.auth){ if(sd->status.party_id==party_id) sd->status.party_id=0; } @@ -164,7 +164,7 @@ int party_recv_info(struct party *sp) nullpo_retr(0, sp); - if((p=numdb_search(party_db,sp->party_id))==NULL){ + if((p=(struct party *) numdb_search(party_db,sp->party_id))==NULL){ p=(struct party *)aCalloc(1,sizeof(struct party)); numdb_insert(party_db,sp->party_id,p); @@ -175,7 +175,7 @@ int party_recv_info(struct party *sp) for(i=0;i<MAX_PARTY;i++){ // sd‚ÌÝ’è struct map_session_data *sd = map_id2sd(p->member[i].account_id); - p->member[i].sd=(sd!=NULL && sd->status.party_id==p->party_id)?sd:NULL; + p->member[i].sd=(sd!=NULL && sd->status.party_id==p->party_id && !sd->state.waitingdisconnect)?sd:NULL; } clif_party_info(p,-1); @@ -250,11 +250,13 @@ int party_reply_invite(struct map_session_data *sd,int account_id,int flag) // ƒp[ƒeƒB‚ª’ljÁ‚³‚ꂽ int party_member_added(int party_id,int account_id,int flag) { - struct map_session_data *sd= map_id2sd(account_id),*sd2; - if(sd==NULL && flag==0){ - if(battle_config.error_log) - printf("party: member added error %d is not online\n",account_id); - intif_party_leave(party_id,account_id); // ƒLƒƒƒ‰‘¤‚É“o˜^‚Å‚«‚È‚©‚Á‚½‚½‚ß’E‘Þ—v‹‚ðo‚· + struct map_session_data *sd = map_id2sd(account_id),*sd2; + if(sd == NULL){ + if (flag == 0) { + if(battle_config.error_log) + printf("party: member added error %d is not online\n",account_id); + intif_party_leave(party_id,account_id); // ƒLƒƒƒ‰‘¤‚É“o˜^‚Å‚«‚È‚©‚Á‚½‚½‚ß’E‘Þ—v‹‚ðo‚· + } return 0; } sd2=map_id2sd(sd->party_invite_account); @@ -417,7 +419,7 @@ int party_recv_movemap(int party_id,int account_id,char *map,int online,int lv) for(i=0;i<MAX_PARTY;i++){ // sdÄÝ’è struct map_session_data *sd= map_id2sd(p->member[i].account_id); - p->member[i].sd=(sd!=NULL && sd->status.party_id==p->party_id)?sd:NULL; + p->member[i].sd=(sd!=NULL && sd->status.party_id==p->party_id && !sd->state.waitingdisconnect)?sd:NULL; } party_send_xy_clear(p); // À•WÄ’Ê’m—v¿ @@ -481,6 +483,7 @@ int party_send_message(struct map_session_data *sd,char *mes,int len) if(sd->status.party_id==0) return 0; intif_party_message(sd->status.party_id,sd->status.account_id,mes,len); + party_recv_message(sd->status.party_id,sd->status.account_id,mes,len); return 0; } @@ -583,16 +586,23 @@ int party_exp_share(struct party *p,int map,int base_exp,int job_exp,int zeny) nullpo_retr(0, p); - for(i=c=0;i<MAX_PARTY;i++) - if((sd=p->member[i].sd)!=NULL && sd->bl.m==map) + for (i=c=0; i < MAX_PARTY; i++) + if ((sd = p->member[i].sd) != NULL && p->member[i].online && sd->bl.m == map /*&& session[sd->fd] != NULL*/) // should be done in socket.c c++; - if(c==0) + + if(c == 0) return 0; - for(i=0;i<MAX_PARTY;i++) - if((sd=p->member[i].sd)!=NULL && sd->bl.m==map) { - pc_gainexp(sd,base_exp/c+1,job_exp/c+1); - if(battle_config.zeny_from_mobs) // zeny from mobs [Valaris] - pc_getzeny(sd,zeny/c+1); + for (i = 0; i < MAX_PARTY; i++) + if ((sd = p->member[i].sd) != NULL && p->member[i].online && sd->bl.m == map /*&& session[sd->fd] != NULL*/) { + if (battle_config.idle_no_share && (/* pc_issit(sd) || */ sd->chatID || (sd->idletime < (tick_ - 120)))) + continue; + #ifdef TWILIGHT + pc_gainexp(sd,base_exp,job_exp); + #else + pc_gainexp(sd,(base_exp/c)+1,(job_exp/c)+1); + #endif + if (battle_config.zeny_from_mobs) // zeny from mobs [Valaris] + pc_getzeny(sd,(zeny/c)+1); } return 0; } diff --git a/src/map/party.h b/src/map/party.h index 5259df7ff..203dd1057 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -13,7 +13,7 @@ void do_final_party(void); struct party *party_search(int party_id); struct party* party_searchname(char *str); -int party_create(struct map_session_data *sd,char *name); +int party_create(struct map_session_data *sd,char *name, int item, int item2); int party_created(int account_id,int fail,int party_id,char *name); int party_request_info(int party_id); int party_invite(struct map_session_data *sd,int account_id); diff --git a/src/map/path.c b/src/map/path.c index b2e0a78a8..c2b852469 100644 --- a/src/map/path.c +++ b/src/map/path.c @@ -168,17 +168,13 @@ static int add_path(int *heap,struct tmp_path *tp,int x,int y,int dist,int dir,i */ static int can_place(struct map_data *m,int x,int y,int flag) { - int c; - nullpo_retr(0, m); - c=read_gatp(m,x,y); - - if(c==1) - return 0; - if(!(flag&0x10000) && c==5) - return 0; - return 1; + if(map_getcellp(m,x,y,CELL_CHKPASS)) + return 1; + else if((flag&0x10000)&&map_getcellp(m,x,y,CELL_CHKGROUND)) + return 1; + return 0; } /*========================================== @@ -246,6 +242,76 @@ int path_blownpos(int m,int x0,int y0,int dx,int dy,int count) } /*========================================== + * êÀËå×îÍô?ª¬Ê¦Òöª«ªÉª¦ª«ªòÚ÷ª¹ + *------------------------------------------ + */ +#define swap(x,y) { int t; t = x; x = y; y = t; } +int path_search_long(struct shootpath_data *spd,int m,int x0,int y0,int x1,int y1) +{ + int dx, dy; + int wx = 0, wy = 0; + int weight; + struct map_data *md; + + if (!map[m].gat) + return 0; + md = &map[m]; + + dx = (x1 - x0); + if (dx < 0) { + swap(x0, x1); + swap(y0, y1); + dx = -dx; + } + dy = (y1 - y0); + + if (spd) { + spd->rx = spd->ry = 0; + spd->len = 1; + spd->x[0] = x0; + spd->y[0] = y0; + } + + if (map_getcellp(md,x1,y1,CELL_CHKWALL)) + return 0; + + if (dx > abs(dy)) { + weight = dx; + if (spd) + spd->ry=1; + } else { + weight = abs(y1 - y0); + if (spd) + spd->rx=1; + } + + while (x0 != x1 || y0 != y1) { + if (map_getcellp(md,x0,y0,CELL_CHKWALL)) + return 0; + wx += dx; + wy += dy; + if (wx >= weight) { + wx -= weight; + x0 ++; + } + if (wy >= weight) { + wy -= weight; + y0 ++; + } else if (wy < 0) { + wy += weight; + y0 --; + } + if (spd && spd->len<MAX_WALKPATH) { + spd->x[spd->len] = x0; + spd->y[spd->len] = y0; + spd->len++; + } + } + + return 1; +} + +/*========================================== * path’Tõ (x0,y0)->(x1,y1) *------------------------------------------ */ @@ -262,7 +328,7 @@ int path_search(struct walkpath_data *wpd,int m,int x0,int y0,int x1,int y1,int if(!map[m].gat) return -1; md=&map[m]; - if(x1<0 || x1>=md->xs || y1<0 || y1>=md->ys || (i=read_gatp(md,x1,y1))==1 || i==5) + if(x1<0 || x1>=md->xs || y1<0 || y1>=md->ys || map_getcellp(md,x1,y1,CELL_CHKNOPASS)) return -1; // easy diff --git a/src/map/pc.c b/src/map/pc.c index 917bbf0a4..e0c13012d 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1,4 +1,4 @@ -// $Id: pc.c 101 2004-11-26 5:47:29 PM Celestia $ +// $Id: pc.c 101 2004-12-13 7:23:07 PM Celestia $ #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -15,6 +15,7 @@ #include "clif.h" #include "intif.h" #include "pc.h" +#include "status.h" #include "npc.h" #include "mob.h" #include "pet.h" @@ -43,29 +44,16 @@ #define PVP_CALCRANK_INTERVAL 1000 // PVP‡ˆÊŒvŽZ‚ÌŠÔŠu -#define STATE_BLIND 0x10 - -static int max_weight_base[MAX_PC_CLASS]; -static int hp_coefficient[MAX_PC_CLASS]; -static int hp_coefficient2[MAX_PC_CLASS]; -static int hp_sigma_val[MAX_PC_CLASS][MAX_LEVEL]; -static int sp_coefficient[MAX_PC_CLASS]; -static int aspd_base[MAX_PC_CLASS][20]; -static char job_bonus[3][MAX_PC_CLASS][MAX_LEVEL]; static int exp_table[14][MAX_LEVEL]; -static char statp[255][7]; +static short statp[MAX_LEVEL]; -/*static struct { - int id; - int max; - struct { - short id,lv; - } need[6]; -} skill_tree[3][MAX_PC_CLASS][100];*/ // moved to pc.h - celest +extern char msg_table[1000][256]; -static int atkmods[3][20]; // •ŠíATKƒTƒCƒYC³(size_fix.txt) -static int refinebonus[5][3]; // ¸?ƒ{?ƒiƒXƒe?ƒuƒ‹(refine_db.txt) -static int percentrefinery[5][10]; // ¸?¬Œ÷—¦(refine_db.txt) +// h-files are for declarations, not for implementations... [Shinomori] +struct skill_tree_entry skill_tree[3][25][MAX_SKILL_TREE]; +// timer for night.day implementation +int day_timer_tid; +int night_timer_tid; static int dirx[8]={0,-1,-1,-1,0,1,1,1}; static int diry[8]={1,1,0,-1,-1,-1,0,1}; @@ -89,11 +77,11 @@ int pc_isGM(struct map_session_data *sd) { if (p == NULL) return 0; return p->level;*/ - + //For console [Wizputer] if ( sd->fd == 0 ) return 99; - + for(i = 0; i < GM_num; i++) if (gm_account[i].account_id == sd->status.account_id) return gm_account[i].level; @@ -128,18 +116,12 @@ int pc_set_gm_level(int account_id, int level) { } GM_num++; - gm_account = realloc(gm_account, sizeof(struct gm_account) * GM_num); + gm_account = (struct gm_account *) aRealloc(gm_account, sizeof(struct gm_account) * GM_num); gm_account[GM_num - 1].account_id = account_id; gm_account[GM_num - 1].level = level; return 0; } -int pc_getrefinebonus(int lv, int type) { - if (lv >= 0 && lv < 5 && type >= 0 && type < 3) - return refinebonus[lv][type]; - return 0; -} - static int distance(int x0, int y0, int x1, int y1) { int dx, dy; @@ -160,6 +142,7 @@ static int pc_invincible_timer(int tid,unsigned int tick,int id,int data) { return 0; } sd->invincible_timer=-1; + skill_unit_move(&sd->bl,tick,1); return 0; } @@ -180,12 +163,12 @@ int pc_delinvincibletimer(struct map_session_data *sd) { delete_timer(sd->invincible_timer,pc_invincible_timer); sd->invincible_timer = -1; } + skill_unit_move(&sd->bl,gettick(),1); return 0; } static int pc_spiritball_timer(int tid,unsigned int tick,int id,int data) { struct map_session_data *sd; - int i; if( (sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC ) return 1; @@ -195,22 +178,26 @@ static int pc_spiritball_timer(int tid,unsigned int tick,int id,int data) { printf("spirit_timer %d != %d\n",sd->spirit_timer[0],tid); return 0; } - sd->spirit_timer[0]=-1; - for(i=1;i<sd->spiritball;i++) { - sd->spirit_timer[i-1] = sd->spirit_timer[i]; - sd->spirit_timer[i] = -1; + + if(sd->spiritball <= 0) { + if(battle_config.error_log) + printf("Spiritballs are already 0 when pc_spiritball_timer gets called"); + sd->spiritball = 0; + return 0; } + sd->spiritball--; - if(sd->spiritball < 0) - sd->spiritball = 0; + // I leave this here as bad example [Shinomori] + //memcpy( &sd->spirit_timer[0], &sd->spirit_timer[1], sizeof(sd->spirit_timer[0]) * sd->spiritball ); + memmove( sd->spirit_timer+0, sd->spirit_timer+1, (sd->spiritball)*sizeof(int) ); + sd->spirit_timer[sd->spiritball]=-1; + clif_spiritball(sd); return 0; } int pc_addspiritball(struct map_session_data *sd,int interval,int max) { - int i; - nullpo_retr(0, sd); if(max > MAX_SKILL_LEVEL) @@ -219,16 +206,13 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max) { sd->spiritball = 0; if(sd->spiritball >= max) { - if(sd->spirit_timer[0] != -1) { + if(sd->spirit_timer[0] != -1) delete_timer(sd->spirit_timer[0],pc_spiritball_timer); - sd->spirit_timer[0] = -1; - } - for(i=1;i<max;i++) { - sd->spirit_timer[i-1] = sd->spirit_timer[i]; - sd->spirit_timer[i] = -1; - } - } - else + // I leave this here as bad example [Shinomori] + //memcpy( &sd->spirit_timer[0], &sd->spirit_timer[1], sizeof(sd->spirit_timer[0]) * (sd->spiritball - 1)); + memmove( sd->spirit_timer+0, sd->spirit_timer+1, (sd->spiritball - 1)*sizeof(int) ); + //sd->spirit_timer[sd->spiritball-1] = -1; // intentionally, but will be overwritten + } else sd->spiritball++; sd->spirit_timer[sd->spiritball-1] = add_timer(gettick()+interval,pc_spiritball_timer,sd->bl.id,0); @@ -276,13 +260,18 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) { nullpo_retr(0, sd); - s_class = pc_calc_base_job(sd->status.class); + s_class = pc_calc_base_job(sd->status.class_); //----------------------- // Ž€–S‚µ‚½ - if(sd->special_state.restart_full_recover) { // ƒIƒVƒŠƒXƒJ?ƒh + if(sd->special_state.restart_full_recover || // ƒIƒVƒŠƒXƒJ?ƒh + sd->state.snovice_flag == 4) { // [Celest] sd->status.hp=sd->status.max_hp; sd->status.sp=sd->status.max_sp; + if (sd->state.snovice_flag == 4) { + sd->state.snovice_flag = 0; + status_change_start(&sd->bl,SkillStatusChangeTable[MO_STEELBODY],1,0,0,0,skill_get_time(MO_STEELBODY,1),0 ); + } } else { if(s_class.job == 0 && battle_config.restart_hp_rate < 50) { //ƒmƒr‚Í”¼•ª‰ñ•œ @@ -310,7 +299,7 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) { /* removed exp penalty on spawn [Valaris] */ - if(type&2 && sd->status.class != 0 && battle_config.zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty) { + if(type&2 && sd->status.class_ != 0 && battle_config.zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty) { int zeny = (int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.); if(zeny < 1) zeny = 1; sd->status.zeny -= zeny; @@ -378,37 +367,40 @@ int pc_makesavestatus(struct map_session_data *sd) { nullpo_retr(0, sd); - // •ž‚ÌF‚ÍF?•¾ŠQ‚ª‘½‚¢‚̂ŕۑ¶?ۂɂ͂µ‚È‚¢ + // •bÌF‚ÍF?•¾ŠQ‚ª‘½‚¢‚̂ŕۑ¶?ۂɂ͂µ‚È‚¢ if(!battle_config.save_clothcolor) sd->status.clothes_color=0; // Ž€–S?‘Ô‚¾‚Á‚½‚Ì‚Åhp‚ð1AˆÊ’u‚ðƒZ?ƒuꊂÉ?X - if(pc_isdead(sd)){ - pc_setrestartvalue(sd,0); - memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point)); - } else { - memcpy(sd->status.last_point.map,sd->mapname,24); - sd->status.last_point.x = sd->bl.x; - sd->status.last_point.y = sd->bl.y; - } - - // ƒZ?ƒu‹ÖŽ~ƒ}ƒbƒv‚¾‚Á‚½‚̂Ŏw’èˆÊ’u‚Ɉړ® - if(map[sd->bl.m].flag.nosave){ - struct map_data *m=&map[sd->bl.m]; - if(strcmp(m->save.map,"SavePoint")==0) + if(!sd->state.waitingdisconnect) { + if(pc_isdead(sd)){ + pc_setrestartvalue(sd,0); memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point)); - else - memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point)); + } else { + memcpy(sd->status.last_point.map,sd->mapname,24); + sd->status.last_point.x = sd->bl.x; + sd->status.last_point.y = sd->bl.y; + } + + // ƒZ?ƒu‹ÖŽ~ƒ}ƒbƒv‚¾‚Á‚½‚̂Ŏw’èˆÊ’u‚Ɉړ® + if(map[sd->bl.m].flag.nosave){ + struct map_data *m=&map[sd->bl.m]; + if(strcmp(m->save.map,"SavePoint")==0) + memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point)); + else + memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point)); + } } //ƒ}ƒi?ƒ|ƒCƒ“ƒg‚ªƒvƒ‰ƒX‚¾‚Á‚½ê‡0‚É if(battle_config.muting_players && sd->status.manner > 0) sd->status.manner = 0; + return 0; } /*========================================== - * Ú?Žž‚̉Šú‰» + * Ú?Žb̉Šú‰» *------------------------------------------ */ int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int login_id1, int client_tick, int sex, int fd) { @@ -437,7 +429,7 @@ int pc_equippoint(struct map_session_data *sd,int n) nullpo_retr(0, sd); - s_class = pc_calc_base_job(sd->status.class); + s_class = pc_calc_base_job(sd->status.class_); if(sd->inventory_data[n]) { ep = sd->inventory_data[n]->equip; @@ -543,8 +535,8 @@ int pc_isequip(struct map_session_data *sd,int n) nullpo_retr(0, sd); item = sd->inventory_data[n]; - sc_data = battle_get_sc_data(&sd->bl); - //s_class = pc_calc_base_job(sd->status.class); + sc_data = status_get_sc_data(&sd->bl); + //s_class = pc_calc_base_job(sd->status.class_); if( battle_config.gm_allequip>0 && pc_isGM(sd)>=battle_config.gm_allequip ) return 1; @@ -559,18 +551,18 @@ int pc_isequip(struct map_session_data *sd,int n) // as it allows all advanced classes to equip items their normal versions // could equip) // - if(((sd->status.class==13 || sd->status.class==4014) && ((1<<7)&item->class) == 0) || // have mounted classes use unmounted equipment [Valaris] - ((sd->status.class==21 || sd->status.class==4022) && ((1<<14)&item->class) == 0)) + if(((sd->status.class_==13 || sd->status.class_==4014) && ((1<<7)&item->class_) == 0) || // have mounted classes use unmounted equipment [Valaris] + ((sd->status.class_==21 || sd->status.class_==4022) && ((1<<14)&item->class_) == 0)) return 0; - if(sd->status.class!=13 && sd->status.class!=4014 && sd->status.class!=21 && sd->status.class!=4022) - if((sd->status.class<=4000 && ((1<<sd->status.class)&item->class) == 0) || (sd->status.class>4000 && sd->status.class<4023 && ((1<<(sd->status.class-4001))&item->class) == 0) || - (sd->status.class>=4023 && ((1<<(sd->status.class-4023))&item->class) == 0)) + if(sd->status.class_!=13 && sd->status.class_!=4014 && sd->status.class_!=21 && sd->status.class_!=4022) + if((sd->status.class_<=4000 && ((1<<sd->status.class_)&item->class_) == 0) || (sd->status.class_>4000 && sd->status.class_<4023 && ((1<<(sd->status.class_-4001))&item->class_) == 0) || + (sd->status.class_>=4023 && ((1<<(sd->status.class_-4023))&item->class_) == 0)) return 0; -// if(((1<<sd->status.class)&item->class) == 0) +// if(((1<<sd->status.class_)&item->class_) == 0) // return 0; - if(map[sd->bl.m].flag.pvp && (item->flag.no_equip==1 || item->flag.no_equip==3)) + if(map[sd->bl.m].flag.pvp && (item->flag.no_equip&1)) //optimized by Lupus return 0; - if(map[sd->bl.m].flag.gvg && (item->flag.no_equip==2 || item->flag.no_equip==3)) + if(map[sd->bl.m].flag.gvg && (item->flag.no_equip>1)) //optimized by Lupus return 0; if(item->equip & 0x0002 && sc_data && sc_data[SC_STRIPWEAPON].timer != -1) return 0; @@ -583,69 +575,52 @@ int pc_isequip(struct map_session_data *sd,int n) return 1; } -/*========================================== - * Weapon Breaking [Valaris] - *------------------------------------------ - */ -int pc_breakweapon(struct map_session_data *sd) +//‘•”õ”j‰ó +int pc_break_equip(struct map_session_data *sd, unsigned short where) { - struct item_data* item; - char output[255]; int i; + int sc; - if(sd==NULL) - return -1; - if(sd->unbreakable>=rand()%100) + nullpo_retr(-1, sd); + if(sd->unbreakable_equip & where) return 0; - if(sd->sc_data && sd->sc_data[SC_CP_WEAPON].timer != -1) + if(sd->unbreakable >= rand()%100) return 0; - - for(i=0;i<MAX_INVENTORY;i++){ - if(sd->status.inventory[i].equip && sd->status.inventory[i].equip & 0x0002 && !sd->status.inventory[i].attribute==1){ - item=sd->inventory_data[i]; - sd->status.inventory[i].attribute=1; - pc_unequipitem(sd,i,0,BF_NORMAL); - sprintf(output, "%s has broken.",item->jname); - clif_emotion(&sd->bl,23); - clif_displaymessage(sd->fd, output); - clif_equiplist(sd); - return 1; - } + switch (where) { + case EQP_WEAPON: + sc = SC_CP_WEAPON; + break; + case EQP_ARMOR: + sc = SC_CP_ARMOR; + break; + case EQP_SHIELD: + sc = SC_CP_SHIELD; + break; + case EQP_HELM: + sc = SC_CP_HELM; + break; + default: + return 0; } - - return 0; -} -/*========================================== - * Armor Breaking [Valaris] - *------------------------------------------ - */ -int pc_breakarmor(struct map_session_data *sd) -{ - struct item_data* item; - char output[255]; - int i; - - if(sd==NULL) - return -1; - if(sd->unbreakable>=rand()%100) - return 0; - if(sd->sc_data && sd->sc_data[SC_CP_ARMOR].timer != -1) + if(sd->sc_count && sd->sc_data[sc].timer != -1) return 0; - for(i=0;i<MAX_INVENTORY;i++){ - if(sd->status.inventory[i].equip && sd->status.inventory[i].equip & 0x0010 && !sd->status.inventory[i].attribute==1){ - item=sd->inventory_data[i]; - sd->status.inventory[i].attribute=1; - pc_unequipitem(sd,i,0,BF_NORMAL); - sprintf(output, "%s has broken.",item->jname); + for (i=0;i<MAX_INVENTORY;i++) { + if (sd->status.inventory[i].equip & where && + sd->status.inventory[i].attribute != 1) { + sd->status.inventory[i].attribute = 1; + pc_unequipitem(sd,i,3); + sprintf(tmp_output, "%s has broken.",sd->inventory_data[i]->jname); clif_emotion(&sd->bl,23); - clif_displaymessage(sd->fd, output); + clif_displaymessage(sd->fd, tmp_output); clif_equiplist(sd); + break; } } - return 0; + return 1; } + /*========================================== * session id‚É–â‘è–³‚µ * charŽI‚©‚ç‘—‚ç‚ê‚Ä‚«‚½ƒXƒe?ƒ^ƒX‚ðÝ’è @@ -663,8 +638,14 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars sd = map_id2sd(id); nullpo_retr(1, sd); + // check if double login occured + if(sd->new_fd){ + // 2dloginó‘Ô‚¾‚Á‚½‚Ì‚ÅA—¼•û—Ž‚· + clif_authfail_fd(sd->fd,2); // same id + clif_authfail_fd(sd->new_fd,8); // same id + return 1; + } sd->login_id2 = login_id2; - memcpy(&sd->status, st, sizeof(*st)); if (sd->status.sex != sd->sex) { @@ -678,21 +659,21 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars sd->bl.prev = sd->bl.next = NULL; sd->weapontype1 = sd->weapontype2 = 0; - sd->view_class = sd->status.class; + sd->view_class = sd->status.class_; sd->speed = DEFAULT_WALK_SPEED; sd->state.dead_sit = 0; sd->dir = 0; sd->head_dir = 0; sd->state.auth = 1; sd->walktimer = -1; + sd->next_walktime = -1; sd->attacktimer = -1; sd->followtimer = -1; // [MouseJstr] sd->skilltimer = -1; sd->skillitem = -1; sd->skillitemlv = -1; sd->invincible_timer = -1; - sd->sg_count = 0; - + sd->deal_locked = 0; sd->trade_partner = 0; @@ -704,11 +685,11 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars sd->inchealspiritsptick = 0; sd->canact_tick = tick; sd->canmove_tick = tick; + sd->canregen_tick = tick; sd->attackabletime = tick; - + sd->reg_num = 0; sd->doridori_counter = 0; - - sd->change_level = pc_readglobalreg(sd,"jobchange_level"); + sd->change_level = pc_readglobalreg(sd,"jobchange_level"); #ifndef TXT_ONLY // mail system [Valaris] if(battle_config.mail_system) @@ -719,13 +700,16 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars sd->spirit_timer[i] = -1; for(i = 0; i < MAX_SKILLTIMERSKILL; i++) sd->skilltimerskill[i].timer = -1; + sd->timerskill_count=0; + + memset(sd->blockskill,0,sizeof(sd->blockskill)); memset(&sd->dev,0,sizeof(struct square)); for(i = 0; i < 5; i++) { sd->dev.val1[i] = 0; sd->dev.val2[i] = 0; } - + // ƒAƒJƒEƒ“ƒg??‚Ì‘—M—v‹ intif_request_accountreg(sd); @@ -753,7 +737,7 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars // ƒXƒLƒ‹ƒ†ƒjƒbƒg?ŒW‚̉Šú‰» memset(sd->skillunit, 0, sizeof(sd->skillunit)); - memset(sd->skillunittick, 0, sizeof(sd->skillunittick)); + memset(sd->skillunittick, 0, sizeof(sd->skillunittick)); // ƒp?ƒeƒB??ŒW‚̉Šú‰» sd->party_sended = 0; @@ -771,9 +755,22 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars memset(sd->eventqueue, 0, sizeof(sd->eventqueue)); for(i = 0; i < MAX_EVENTTIMER; i++) sd->eventtimer[i] = -1; + sd->eventcount=0; // ˆÊ’u‚ÌÝ’è - pc_setpos(sd,sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, 0); + if (pc_setpos(sd,sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, 0) != 0) { + if(battle_config.error_log) { + char buf[32]; + sprintf(buf, "Last_point_map %s not found\n", sd->status.last_point.map); + ShowError (buf); + } + // try warping to a default map instead + if (pc_setpos(sd, "prontera.gat", 273, 354, 0) != 0) { + // if we fail again + clif_authfail_fd(sd->fd, 0); + return 1; + } + } // pet if (sd->status.pet_id > 0) @@ -800,6 +797,18 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars //ƒXƒpƒmƒr—pŽ€‚ɃJƒEƒ“ƒ^?‚̃XƒNƒŠƒvƒg??‚©‚ç‚Ì?‚Ýo‚µ‚Æsd‚ւ̃Zƒbƒg sd->die_counter = pc_readglobalreg(sd,"PC_DIE_COUNTER"); + // Automated script events + if (script_config.event_requires_trigger) { + sd->state.event_death = pc_readglobalreg(sd, script_config.die_event_name); + sd->state.event_kill = pc_readglobalreg(sd, script_config.kill_event_name); + sd->state.event_disconnect = pc_readglobalreg(sd, script_config.logout_event_name); + // if script triggers are not required + } else { + sd->state.event_death = 1; + sd->state.event_kill = 1; + sd->state.event_disconnect = 1; + } + if (night_flag == 1 && !map[sd->bl.m].flag.indoors) { char tmpstr[1024]; strcpy(tmpstr, msg_txt(500)); // Actually, it's the night... @@ -812,16 +821,28 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars } // ƒXƒe?ƒ^ƒX‰ŠúŒvŽZ‚È‚Ç - pc_calcstatus(sd,1); + status_calc_pc(sd,1); if (pc_isGM(sd)) - printf("Connection accepted: character '%s' (account: %d; GM level %d).\n", sd->status.name, sd->status.account_id, pc_isGM(sd)); + sprintf(tmp_output,"GM Character '"CL_WHITE"%s"CL_RESET"' logged in. (Acc. ID: '"CL_WHITE"%d"CL_RESET"', GM Level '"CL_WHITE"%d"CL_RESET"').\n", sd->status.name, sd->status.account_id, pc_isGM(sd)); else - printf("Connection accepted: Character '%s' (account: %d).\n", sd->status.name, sd->status.account_id); + sprintf(tmp_output,"Character '"CL_WHITE"%s"CL_RESET"' logged in. (Account ID: '"CL_WHITE"%d"CL_RESET"').\n", sd->status.name, sd->status.account_id); + ShowInfo(tmp_output); + + if (script_config.event_script_type == 0) { + struct npc_data *npc; + //printf("pc: OnPCLogin event done. (%d events)\n", npc_event_doall("OnPCLogin") ); + if ((npc = npc_name2id(script_config.login_event_name))) { + run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLoginNPC + sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.login_event_name); + ShowStatus(tmp_output); + } + } else { + sprintf (tmp_output, "%d '"CL_WHITE"%s"CL_RESET"' events executed.\n", + npc_event_doall_id(script_config.login_event_name, sd->bl.id), script_config.login_event_name); + ShowStatus(tmp_output); + } - //printf("pc: OnPCLogin event done. (%d events)\n", npc_event_doall("OnPCLogin") ); - if (npc_name2id("PCLoginEvent")) - run_script(npc_name2id("PCLoginEvent")->u.scr.script,0,sd->bl.id,npc_name2id("PCLoginEvent")->bl.id); // PCLoginNPC // Send friends list clif_friends_list_send(sd); @@ -838,13 +859,16 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars break; } } - clif_displaymessage(sd->fd, buf); + if (battle_config.motd_type) + clif_disp_onlyself(sd,buf,strlen(buf)); + else + clif_displaymessage(sd->fd, buf); } fclose(fp); } else if(battle_config.error_log) { - sprintf(buf, "%s not found\n", motd_txt); - ShowWarning (buf); + sprintf(tmp_output, "In function pc_atuhok() -> File '"CL_WHITE"%s"CL_RESET"' not found.\n", motd_txt); + ShowWarning(tmp_output); } } @@ -874,6 +898,13 @@ int pc_authfail(int id) { if (sd == NULL) return 1; + if(sd->new_fd){ + // 2dloginó‘Ô‚¾‚Á‚½‚Ì‚ÅAV‚µ‚¢Ú‘±‚Ì‚Ý—Ž‚· + clif_authfail_fd(sd->new_fd,0); + sd->new_fd=0; + return 0; + } + clif_authfail_fd(sd->fd, 0); return 0; @@ -913,7 +944,7 @@ int pc_calc_skilltree(struct map_session_data *sd) nullpo_retr(0, sd); - s_class = pc_calc_base_job(sd->status.class); + s_class = pc_calc_base_job(sd->status.class_); c = s_class.job; //s = (s_class.upper==1) ? 1 : 0 ; //?¶ˆÈŠO‚Í’Êí‚̃XƒLƒ‹H s = s_class.upper; @@ -921,7 +952,10 @@ int pc_calc_skilltree(struct map_session_data *sd) c = pc_calc_skilltree_normalize_job(c, sd); for(i=0;i<MAX_SKILL;i++){ - if (sd->status.skill[i].flag != 13) sd->status.skill[i].id=0; +// if(skill_get_inf2(i) & 0x01) +// continue; + if (sd->status.skill[i].flag != 13) + sd->status.skill[i].id=0; if (sd->status.skill[i].flag && sd->status.skill[i].flag != 13){ // cardƒXƒLƒ‹‚È‚çA sd->status.skill[i].lv=(sd->status.skill[i].flag==1)?0:sd->status.skill[i].flag-2; // –{?‚Ìlv‚É sd->status.skill[i].flag=0; // flag‚Í0‚É‚µ‚Ä‚¨‚ @@ -934,39 +968,60 @@ int pc_calc_skilltree(struct map_session_data *sd) sd->status.skill[i].id=i; for(i=210;i<291;i++) sd->status.skill[i].id=i; - for(i=304;i<337;i++){ + for(i=304;i<338;i++){ if(i==331) continue; sd->status.skill[i].id=i; } - if(battle_config.enable_upper_class){ //conf‚Å–³?‚łȂ¯‚ê‚Î?‚Ý?‚Þ - for(i=355;i<MAX_SKILL;i++) + for(i=355;i<411;i++) sd->status.skill[i].id=i; - } - }else{ - // ’Êí‚ÌŒvŽZ - do{ - flag=0; - for(i=0;(id=skill_tree[s][c][i].id)>0;i++){ - int j,f=1; - if(!battle_config.skillfree) { - for(j=0;j<5;j++) { - if( skill_tree[s][c][i].need[j].id && - pc_checkskill(sd,skill_tree[s][c][i].need[j].id) < skill_tree[s][c][i].need[j].lv) + for(i=475;i<480;i++) + sd->status.skill[i].id=i; + } else { + do { + flag=0; + for(i=0;(id=skill_tree[s][c][i].id)>0;i++){ + int j,f=1; + if(!battle_config.skillfree) { + for(j=0;j<5;j++) { + if( skill_tree[s][c][i].need[j].id && + pc_checkskill(sd,skill_tree[s][c][i].need[j].id) < + skill_tree[s][c][i].need[j].lv) { + f=0; + break; + } + } + if (sd->status.job_level < skill_tree[s][c][i].joblv) f=0; + else if (id >= 2 && id <= 53 && pc_checkskill(sd, NV_BASIC) < 9) + f=0; + } + if(f && sd->status.skill[id].id==0 ){ + sd->status.skill[id].id=id; + flag=1; } } - if(f && sd->status.skill[id].id==0 ){ - sd->status.skill[id].id=id; - flag=1; - } - } - }while(flag); + } while(flag); } // if(battle_config.etc_log) // printf("calc skill_tree\n"); return 0; } +// Make sure all the skills are in the correct condition +// before persisting to the backend.. [MouseJstr] +int pc_clean_skilltree(struct map_session_data *sd) { + int i; + for (i = 0; i < MAX_SKILL; i++){ + if (sd->status.skill[i].flag == 13){ + sd->status.skill[i].id = 0; + sd->status.skill[i].lv = 0; + sd->status.skill[i].flag = 0; + } + } + + return 0; +} + int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) { //if((battle_config.skillup_limit) && ((c >= 0 && c < 23) || (c >= 4001 && c < 4023) || (c >= 4023 && c < 4045))) { if (battle_config.skillup_limit && c >= 0 && c < 23) { @@ -975,10 +1030,12 @@ int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) { c = 0; //else if((sd->status.skill_point >= sd->status.job_level && skill_point < 58) && ((c > 6 && c < 23) || (c > 4007 && c < 4023) || (c > 4029 && c < 4045))) { //else if ((sd->status.skill_point >= sd->status.job_level && skill_point < 58) && (c > 6 && c < 23)) { - else if ((sd->status.skill_point >= sd->status.job_level && skill_point < sd->change_level+8) && (c > 6 && c < 23)) { + else if (sd->status.skill_point >= sd->status.job_level && ((sd->change_level > 0 && skill_point < sd->change_level+8) || skill_point < 58) && (c > 6 && c < 23)) { switch(c) { case 7: + case 13: case 14: + case 21: c = 1; break; case 8: @@ -1002,8 +1059,11 @@ int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) { case 17: c = 6; break; - /*case 4008: +#if 0 + case 4008: + case 4014: case 4015: + case 4022: c = 4002; break; case 4009: @@ -1028,7 +1088,9 @@ int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) { c = 4007; break; case 4030: + case 4036: case 4037: + case 4044: c = 4024; break; case 4031: @@ -1051,7 +1113,8 @@ int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) { case 4035: case 4043: c = 4029; - break;*/ + break; +#endif } } } @@ -1072,1127 +1135,29 @@ int pc_checkweighticon(struct map_session_data *sd) flag=1; if(sd->weight*10 >= sd->max_weight*9) flag=2; - + if(flag==1){ if(sd->sc_data[SC_WEIGHT50].timer==-1) - skill_status_change_start(&sd->bl,SC_WEIGHT50,0,0,0,0,0,0); + status_change_start(&sd->bl,SC_WEIGHT50,0,0,0,0,0,0); }else{ - skill_status_change_end(&sd->bl,SC_WEIGHT50,-1); + status_change_end(&sd->bl,SC_WEIGHT50,-1); } if(flag==2){ if(sd->sc_data[SC_WEIGHT90].timer==-1) - skill_status_change_start(&sd->bl,SC_WEIGHT90,0,0,0,0,0,0); + status_change_start(&sd->bl,SC_WEIGHT90,0,0,0,0,0,0); }else{ - skill_status_change_end(&sd->bl,SC_WEIGHT90,-1); + status_change_end(&sd->bl,SC_WEIGHT90,-1); } return 0; } /*========================================== - * ƒpƒ‰ƒ?ƒ^ŒvŽZ - * first==0‚ÌŽžAŒvŽZ?ۂ̃pƒ‰ƒ?ƒ^‚ªŒÄ‚Ño‚µ‘O‚©‚ç - * ? ‰»‚µ‚½ê‡Ž©“®‚Åsend‚·‚邪A - * ”\“®“I‚É?‰»‚³‚¹‚½ƒpƒ‰ƒ?ƒ^‚ÍŽ©‘O‚Åsend‚·‚邿‚¤‚É - *------------------------------------------ - */ -int pc_calcstatus(struct map_session_data* sd,int first) -{ - int b_speed,b_max_hp,b_max_sp,b_hp,b_sp,b_weight,b_max_weight,b_paramb[6],b_parame[6],b_hit,b_flee; - int b_aspd,b_watk,b_def,b_watk2,b_def2,b_flee2,b_critical,b_attackrange,b_matk1,b_matk2,b_mdef,b_mdef2,b_class; - int b_base_atk; - struct skill b_skill[MAX_SKILL]; - int i,bl,index; - int skill,aspd_rate,wele,wele_,def_ele,refinedef=0; - int pele=0,pdef_ele=0; - int str,dstr,dex; - struct pc_base_job s_class; - - nullpo_retr(0, sd); - - //?¶‚â—{Žq‚Ìꇂ̌³‚ÌE‹Æ‚ðŽZo‚·‚é - s_class = pc_calc_base_job(sd->status.class); - - b_speed = sd->speed; - b_max_hp = sd->status.max_hp; - b_max_sp = sd->status.max_sp; - b_hp = sd->status.hp; - b_sp = sd->status.sp; - b_weight = sd->weight; - b_max_weight = sd->max_weight; - memcpy(b_paramb,&sd->paramb,sizeof(b_paramb)); - memcpy(b_parame,&sd->paramc,sizeof(b_parame)); - memcpy(b_skill,&sd->status.skill,sizeof(b_skill)); - b_hit = sd->hit; - b_flee = sd->flee; - b_aspd = sd->aspd; - b_watk = sd->watk; - b_def = sd->def; - b_watk2 = sd->watk2; - b_def2 = sd->def2; - b_flee2 = sd->flee2; - b_critical = sd->critical; - b_attackrange = sd->attackrange; - b_matk1 = sd->matk1; - b_matk2 = sd->matk2; - b_mdef = sd->mdef; - b_mdef2 = sd->mdef2; - b_class = sd->view_class; - sd->view_class = sd->status.class; - b_base_atk = sd->base_atk; - - pc_calc_skilltree(sd); // ƒXƒLƒ‹ƒcƒŠ?‚ÌŒvŽZ - - sd->max_weight = max_weight_base[s_class.job]+sd->status.str*300; - - if(first&1) { - sd->weight=0; - for(i=0;i<MAX_INVENTORY;i++){ - if(sd->status.inventory[i].nameid==0 || sd->inventory_data[i] == NULL) - continue; - sd->weight += sd->inventory_data[i]->weight*sd->status.inventory[i].amount; - } - sd->cart_max_weight=battle_config.max_cart_weight; - sd->cart_weight=0; - sd->cart_max_num=MAX_CART; - sd->cart_num=0; - for(i=0;i<MAX_CART;i++){ - if(sd->status.cart[i].nameid==0) - continue; - sd->cart_weight+=itemdb_weight(sd->status.cart[i].nameid)*sd->status.cart[i].amount; - sd->cart_num++; - } - } - - memset(sd->paramb,0,sizeof(sd->paramb)); - memset(sd->parame,0,sizeof(sd->parame)); - sd->hit = 0; - sd->flee = 0; - sd->flee2 = 0; - sd->critical = 0; - sd->aspd = 0; - sd->watk = 0; - sd->def = 0; - sd->mdef = 0; - sd->watk2 = 0; - sd->def2 = 0; - sd->mdef2 = 0; - sd->status.max_hp = 0; - sd->status.max_sp = 0; - sd->attackrange = 0; - sd->attackrange_ = 0; - sd->atk_ele = 0; - sd->def_ele = 0; - sd->star =0; - sd->overrefine =0; - sd->matk1 =0; - sd->matk2 =0; - sd->speed = DEFAULT_WALK_SPEED ; - sd->hprate=100; - sd->sprate=100; - sd->castrate=100; - sd->dsprate=100; - sd->base_atk=0; - sd->arrow_atk=0; - sd->arrow_ele=0; - sd->arrow_hit=0; - sd->arrow_range=0; - sd->nhealhp=sd->nhealsp=sd->nshealhp=sd->nshealsp=sd->nsshealhp=sd->nsshealsp=0; - memset(sd->addele,0,sizeof(sd->addele)); - memset(sd->addrace,0,sizeof(sd->addrace)); - memset(sd->addsize,0,sizeof(sd->addsize)); - memset(sd->addele_,0,sizeof(sd->addele_)); - memset(sd->addrace_,0,sizeof(sd->addrace_)); - memset(sd->addsize_,0,sizeof(sd->addsize_)); - memset(sd->subele,0,sizeof(sd->subele)); - memset(sd->subrace,0,sizeof(sd->subrace)); - memset(sd->addeff,0,sizeof(sd->addeff)); - memset(sd->addeff2,0,sizeof(sd->addeff2)); - memset(sd->reseff,0,sizeof(sd->reseff)); - memset(&sd->special_state,0,sizeof(sd->special_state)); - memset(sd->weapon_coma_ele,0,sizeof(sd->weapon_coma_ele)); - memset(sd->weapon_coma_race,0,sizeof(sd->weapon_coma_race)); - - sd->watk_ = 0; //“ñ“—¬—p(?) - sd->watk_2 = 0; - sd->atk_ele_ = 0; - sd->star_ = 0; - sd->overrefine_ = 0; - - sd->aspd_rate = 100; - sd->speed_rate = 100; - sd->hprecov_rate = 100; - sd->sprecov_rate = 100; - sd->critical_def = 0; - sd->double_rate = 0; - sd->near_attack_def_rate = sd->long_attack_def_rate = 0; - sd->atk_rate = sd->matk_rate = 100; - sd->ignore_def_ele = sd->ignore_def_race = 0; - sd->ignore_def_ele_ = sd->ignore_def_race_ = 0; - sd->ignore_mdef_ele = sd->ignore_mdef_race = 0; - sd->arrow_cri = 0; - sd->magic_def_rate = sd->misc_def_rate = 0; - memset(sd->arrow_addele,0,sizeof(sd->arrow_addele)); - memset(sd->arrow_addrace,0,sizeof(sd->arrow_addrace)); - memset(sd->arrow_addsize,0,sizeof(sd->arrow_addsize)); - memset(sd->arrow_addeff,0,sizeof(sd->arrow_addeff)); - memset(sd->arrow_addeff2,0,sizeof(sd->arrow_addeff2)); - memset(sd->magic_addele,0,sizeof(sd->magic_addele)); - memset(sd->magic_addrace,0,sizeof(sd->magic_addrace)); - memset(sd->magic_subrace,0,sizeof(sd->magic_subrace)); - sd->perfect_hit = 0; - sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100; - sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100; - sd->def_ratio_atk_ele = sd->def_ratio_atk_ele_ = 0; - sd->def_ratio_atk_race = sd->def_ratio_atk_race_ = 0; - sd->get_zeny_num = 0; - sd->add_damage_class_count = sd->add_damage_class_count_ = sd->add_magic_damage_class_count = 0; - sd->add_def_class_count = sd->add_mdef_class_count = 0; - sd->monster_drop_item_count = 0; - memset(sd->add_damage_classrate,0,sizeof(sd->add_damage_classrate)); - memset(sd->add_damage_classrate_,0,sizeof(sd->add_damage_classrate_)); - memset(sd->add_magic_damage_classrate,0,sizeof(sd->add_magic_damage_classrate)); - memset(sd->add_def_classrate,0,sizeof(sd->add_def_classrate)); - memset(sd->add_mdef_classrate,0,sizeof(sd->add_mdef_classrate)); - memset(sd->monster_drop_race,0,sizeof(sd->monster_drop_race)); - memset(sd->monster_drop_itemrate,0,sizeof(sd->monster_drop_itemrate)); - sd->speed_add_rate = sd->aspd_add_rate = 100; - sd->double_add_rate = sd->perfect_hit_add = sd->get_zeny_add_num = 0; - sd->splash_range = sd->splash_add_range = 0; - sd->autospell_id = sd->autospell_lv = sd->autospell_rate = 0; - sd->hp_drain_rate = sd->hp_drain_per = sd->sp_drain_rate = sd->sp_drain_per = 0; - sd->hp_drain_rate_ = sd->hp_drain_per_ = sd->sp_drain_rate_ = sd->sp_drain_per_ = 0; - sd->short_weapon_damage_return = sd->long_weapon_damage_return = 0; - sd->magic_damage_return = 0; //AppleGirl Was Here - sd->random_attack_increase_add = sd->random_attack_increase_per = 0; - - if(!sd->disguiseflag && sd->disguise) { - sd->disguise=0; - clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); - clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); - clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); - clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); - clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); - clif_clearchar(&sd->bl, 9); - pc_setpos(sd, sd->mapname, sd->bl.x, sd->bl.y, 3); - } - - for(i=0;i<10;i++) { - index = sd->equip_index[i]; - if(index < 0) - continue; - if(i == 9 && sd->equip_index[8] == index) - continue; - if(i == 5 && sd->equip_index[4] == index) - continue; - if(i == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index)) - continue; - - if(sd->inventory_data[index]) { - if(sd->inventory_data[index]->type == 4) { - if(sd->status.inventory[index].card[0]!=0x00ff && sd->status.inventory[index].card[0]!=0x00fe && sd->status.inventory[index].card[0]!=(short)0xff00) { - int j; - for(j=0;j<sd->inventory_data[index]->slot;j++){ // ƒJ?ƒh - int c=sd->status.inventory[index].card[j]; - if(c>0){ - if(i == 8 && sd->status.inventory[index].equip == 0x20) - sd->state.lr_flag = 1; - run_script(itemdb_equipscript(c),0,sd->bl.id,0); - sd->state.lr_flag = 0; - } - } - } - } - else if(sd->inventory_data[index]->type==5){ // –h‹ï - if(sd->status.inventory[index].card[0]!=0x00ff && sd->status.inventory[index].card[0]!=0x00fe && sd->status.inventory[index].card[0]!=(short)0xff00) { - int j; - for(j=0;j<sd->inventory_data[index]->slot;j++){ // ƒJ?ƒh - int c=sd->status.inventory[index].card[j]; - if(c>0) - run_script(itemdb_equipscript(c),0,sd->bl.id,0); - } - } - } - } - } - wele = sd->atk_ele; - wele_ = sd->atk_ele_; - def_ele = sd->def_ele; - if(sd->status.pet_id > 0) { - struct pet_data *pd=sd->pd; - if((pd && battle_config.pet_status_support==1) && (battle_config.pet_equip_required==0 || (battle_config.pet_equip_required && pd->equip > 0))) { - if(sd->status.pet_id > 0 && sd->petDB && sd->pet.intimate > 0) - run_script(sd->petDB->script,0,sd->bl.id,0); - pele = sd->atk_ele; - pdef_ele = sd->def_ele; - sd->atk_ele = sd->def_ele = 0; - } - } - memcpy(sd->paramcard,sd->parame,sizeof(sd->paramcard)); - - // ?”õ•i‚É‚æ‚éƒXƒe?ƒ^ƒX?‰»‚Í‚±‚±‚Å?s - for(i=0;i<10;i++) { - index = sd->equip_index[i]; - if(index < 0) - continue; - if(i == 9 && sd->equip_index[8] == index) - continue; - if(i == 5 && sd->equip_index[4] == index) - continue; - if(i == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index)) - continue; - if(sd->inventory_data[index]) { - sd->def += sd->inventory_data[index]->def; - if(sd->inventory_data[index]->type == 4) { - int r,wlv = sd->inventory_data[index]->wlv; - if(i == 8 && sd->status.inventory[index].equip == 0x20) { - //“ñ“—¬—pƒf?ƒ^“ü—Í - sd->watk_ += sd->inventory_data[index]->atk; - sd->watk_2 = (r=sd->status.inventory[index].refine)* // ¸?U?—Í - refinebonus[wlv][0]; - if( (r-=refinebonus[wlv][2])>0 ) // ‰ß?¸?ƒ{?ƒiƒX - sd->overrefine_ = r*refinebonus[wlv][1]; - - if(sd->status.inventory[index].card[0]==0x00ff){ // »‘¢•Ší - sd->star_ = (sd->status.inventory[index].card[1]>>8); // ¯‚Ì‚©‚¯‚ç - wele_= (sd->status.inventory[index].card[1]&0x0f); // ? « - } - sd->attackrange_ += sd->inventory_data[index]->range; - sd->state.lr_flag = 1; - run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); - sd->state.lr_flag = 0; - } - else { //“ñ“—¬•ŠíˆÈŠO - sd->watk += sd->inventory_data[index]->atk; - sd->watk2 += (r=sd->status.inventory[index].refine)* // ¸?U?—Í - refinebonus[wlv][0]; - if( (r-=refinebonus[wlv][2])>0 ) // ‰ß?¸?ƒ{?ƒiƒX - sd->overrefine += r*refinebonus[wlv][1]; - - if(sd->status.inventory[index].card[0]==0x00ff){ // »‘¢•Ší - sd->star += (sd->status.inventory[index].card[1]>>8); // ¯‚Ì‚©‚¯‚ç - wele = (sd->status.inventory[index].card[1]&0x0f); // ? « - } - sd->attackrange += sd->inventory_data[index]->range; - run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); - } - } - else if(sd->inventory_data[index]->type == 5) { - sd->watk += sd->inventory_data[index]->atk; - refinedef += sd->status.inventory[index].refine*refinebonus[0][0]; - run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); - } - } - } - - if(sd->equip_index[10] >= 0){ // –î - index = sd->equip_index[10]; - if(sd->inventory_data[index]){ //‚Ü‚¾?«‚ª“ü‚Á‚Ä‚¢‚È‚¢ - sd->state.lr_flag = 2; - run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); - sd->state.lr_flag = 0; - sd->arrow_atk += sd->inventory_data[index]->atk; - } - } - sd->def += (refinedef+50)/100; - - if(sd->attackrange < 1) sd->attackrange = 1; - if(sd->attackrange_ < 1) sd->attackrange_ = 1; - if(sd->attackrange < sd->attackrange_) - sd->attackrange = sd->attackrange_; - if(sd->status.weapon == 11) - sd->attackrange += sd->arrow_range; - if(wele > 0) - sd->atk_ele = wele; - if(wele_ > 0) - sd->atk_ele_ = wele_; - if(def_ele > 0) - sd->def_ele = def_ele; - if(battle_config.pet_status_support) { - if(pele > 0 && !sd->atk_ele) - sd->atk_ele = pele; - if(pdef_ele > 0 && !sd->def_ele) - sd->def_ele = pdef_ele; - } - sd->double_rate += sd->double_add_rate; - sd->perfect_hit += sd->perfect_hit_add; - sd->get_zeny_num += sd->get_zeny_add_num; - sd->splash_range += sd->splash_add_range; - if(sd->speed_add_rate != 100) - sd->speed_rate += sd->speed_add_rate - 100; - if(sd->aspd_add_rate != 100) - sd->aspd_rate += sd->aspd_add_rate - 100; - - // •ŠíATKƒTƒCƒY•â³ (‰EŽè) - sd->atkmods[0] = atkmods[0][sd->weapontype1]; - sd->atkmods[1] = atkmods[1][sd->weapontype1]; - sd->atkmods[2] = atkmods[2][sd->weapontype1]; - //•ŠíATKƒTƒCƒY•â³ (¶Žè) - sd->atkmods_[0] = atkmods[0][sd->weapontype2]; - sd->atkmods_[1] = atkmods[1][sd->weapontype2]; - sd->atkmods_[2] = atkmods[2][sd->weapontype2]; - - // jobƒ{?ƒiƒX•ª - for(i=0;i<sd->status.job_level && i<MAX_LEVEL;i++){ - if(job_bonus[s_class.upper][s_class.job][i]) - sd->paramb[job_bonus[s_class.upper][s_class.job][i]-1]++; - } - - if( (skill=pc_checkskill(sd,MC_INCCARRY))>0 ) // skill can be used with an item now, thanks to orn [Valaris] - sd->max_weight += skill*1000; - - if( (skill=pc_checkskill(sd,AC_OWL))>0 ) // ‚Ó‚‚낤‚Ì–Ú - sd->paramb[4] += skill; - - if((skill=pc_checkskill(sd,BS_HILTBINDING))>0) { // Hilt binding gives +1 str +4 atk - sd->paramb[0] ++; - sd->base_atk += 4; - } - - // New guild skills - Celest - if (sd->status.guild_id > 0) { - struct guild *g; - if ((g = guild_search(sd->status.guild_id)) && strcmp(sd->status.name,g->master)==0) { - if (!sd->sc_data[SC_LEADERSHIP].val4 && guild_checkskill(g, GD_LEADERSHIP)>0) { - //skill_status_change_start(&sd->bl,SC_LEADERSHIP,1,0,0,0,0,0 ); - skill_unitsetting(&sd->bl,GD_LEADERSHIP,1,sd->bl.x,sd->bl.y,0); - } - if (!sd->sc_data[SC_GLORYWOUNDS].val4 && guild_checkskill(g, GD_GLORYWOUNDS)>0) { - //skill_status_change_start(&sd->bl,SC_GLORYWOUNDS,1,0,0,0,0,0 ); - skill_unitsetting(&sd->bl,GD_GLORYWOUNDS,1,sd->bl.x,sd->bl.y,0); - } - if (!sd->sc_data[SC_SOULCOLD].val4 && guild_checkskill(g, GD_SOULCOLD)>0) { - //skill_status_change_start(&sd->bl,SC_SOULCOLD,1,0,0,0,0,0 ); - skill_unitsetting(&sd->bl,GD_SOULCOLD,1,sd->bl.x,sd->bl.y,0); - } - if (!sd->sc_data[SC_HAWKEYES].val4 && guild_checkskill(g, GD_HAWKEYES)>0) { - //skill_status_change_start(&sd->bl,SC_HAWKEYES,1,0,0,0,0,0 ); - skill_unitsetting(&sd->bl,GD_HAWKEYES,1,sd->bl.x,sd->bl.y,0); - } - } - else { - if (sd->sc_data[SC_LEADERSHIP].timer != -1) - sd->paramb[0] += 2; - if (sd->sc_data[SC_GLORYWOUNDS].timer != -1) - sd->paramb[2] += 2; - if (sd->sc_data[SC_SOULCOLD].timer != -1) - sd->paramb[1] += 2; - if (sd->sc_data[SC_HAWKEYES].timer != -1) - sd->paramb[4] += 2; - if (sd->sc_data[SC_BATTLEORDERS].timer != -1) { - sd->paramb[0]+= 5; - sd->paramb[3]+= 5; - sd->paramb[4]+= 5; - } - } - } - - // ƒXƒe?ƒ^ƒX?‰»‚É‚æ‚éŠî–{ƒpƒ‰ƒ?ƒ^•â³ - if(sd->sc_count){ - if(sd->sc_data[SC_CONCENTRATE].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1){ // W’†—ÍŒüã - sd->paramb[1]+= (sd->status.agi+sd->paramb[1]+sd->parame[1]-sd->paramcard[1])*(2+sd->sc_data[SC_CONCENTRATE].val1)/100; - sd->paramb[4]+= (sd->status.dex+sd->paramb[4]+sd->parame[4]-sd->paramcard[4])*(2+sd->sc_data[SC_CONCENTRATE].val1)/100; - } - if(sd->sc_data[SC_INCREASEAGI].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1){ // ‘¬“x?‰Á - sd->paramb[1]+= 2+sd->sc_data[SC_INCREASEAGI].val1; - sd->speed -= sd->speed *25/100; - } - if(sd->sc_data[SC_DECREASEAGI].timer!=-1) // ‘¬“xŒ¸(agi‚Íbattle.c‚Å) - sd->speed = sd->speed *125/100; - if(sd->sc_data[SC_CLOAKING].timer!=-1) { - sd->critical_rate += 100; // critical increases - sd->speed = sd->speed * (sd->sc_data[SC_CLOAKING].val3-sd->sc_data[SC_CLOAKING].val1*3) /100; - // Ours is accurate enough - refer skill_check_cloaking. ^^ - //sd->speed = (sd->speed*(76+(sd->sc_data[SC_CLOAKING].val1*3)))/100; // Fixed by MiKa & Asa [Lupus] - } - //sd->speed = (sd->speed*(76+(sd->sc_data[SC_INCREASEAGI].val1*3)))/100; - if(sd->sc_data[SC_CHASEWALK].timer!=-1) - sd->speed = sd->speed * sd->sc_data[SC_CHASEWALK].val3 /100; // slow down by chasewalk - if(sd->sc_data[SC_BLESSING].timer!=-1){ // ƒuƒŒƒbƒVƒ“ƒO - sd->paramb[0]+= sd->sc_data[SC_BLESSING].val1; - sd->paramb[3]+= sd->sc_data[SC_BLESSING].val1; - sd->paramb[4]+= sd->sc_data[SC_BLESSING].val1; - } - if(sd->sc_data[SC_GLORIA].timer!=-1) // ƒOƒƒŠƒA - sd->paramb[5]+= 30; - if(sd->sc_data[SC_LOUD].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1) // ƒ‰ƒEƒhƒ{ƒCƒX - sd->paramb[0]+= 4; - if(sd->sc_data[SC_QUAGMIRE].timer!=-1){ // ƒNƒ@ƒOƒ}ƒCƒA - int agib = (sd->status.agi+sd->paramb[1]+sd->parame[1])*(sd->sc_data[SC_QUAGMIRE].val1*10)/100; - int dexb = (sd->status.dex+sd->paramb[4]+sd->parame[4])*(sd->sc_data[SC_QUAGMIRE].val1*10)/100; - sd->paramb[1]-= agib > 50 ? 50 : agib; - sd->paramb[4]-= dexb > 50 ? 50 : dexb; - sd->speed = sd->speed*3/2; - } - if(sd->sc_data[SC_TRUESIGHT].timer!=-1){ // ƒgƒDƒ‹?ƒTƒCƒg - sd->paramb[0]+= 5; - sd->paramb[1]+= 5; - sd->paramb[2]+= 5; - sd->paramb[3]+= 5; - sd->paramb[4]+= 5; - sd->paramb[5]+= 5; - } - if(sd->sc_data[SC_MARIONETTE].timer!=-1){ - sd->paramb[0]-= sd->status.str/2; // bonuses not included - sd->paramb[1]-= sd->status.agi/2; - sd->paramb[2]-= sd->status.vit/2; - sd->paramb[3]-= sd->status.int_/2; - sd->paramb[4]-= sd->status.dex/2; - sd->paramb[5]-= sd->status.luk/2; - } - else if(sd->sc_data[SC_MARIONETTE2].timer!=-1){ - struct map_session_data *psd = (struct map_session_data *)map_id2bl(sd->sc_data[SC_MARIONETTE2].val3); - if (psd) { // if partner is found - sd->paramb[0] += sd->status.str+psd->status.str/2 > 99 ? 99-sd->status.str : psd->status.str/2; - sd->paramb[1] += sd->status.agi+psd->status.agi/2 > 99 ? 99-sd->status.agi : psd->status.agi/2; - sd->paramb[2] += sd->status.vit+psd->status.vit/2 > 99 ? 99-sd->status.vit : psd->status.vit/2; - sd->paramb[3] += sd->status.int_+psd->status.int_/2 > 99 ? 99-sd->status.int_ : psd->status.int_/2; - sd->paramb[4] += sd->status.dex+psd->status.dex/2 > 99 ? 99-sd->status.dex : psd->status.dex/2; - sd->paramb[5] += sd->status.luk+psd->status.luk/2 > 99 ? 99-sd->status.luk : psd->status.luk/2; - } - } - } - - //1“x‚àŽ€‚ñ‚łȂ¢Job70ƒXƒpƒmƒr‚É+10 - if(s_class.job == 23 && sd->die_counter == 0 && sd->status.job_level >= 70){ - sd->paramb[0]+= 15; - sd->paramb[1]+= 15; - sd->paramb[2]+= 15; - sd->paramb[3]+= 15; - sd->paramb[4]+= 15; - sd->paramb[5]+= 15; - } - sd->paramc[0]=sd->status.str+sd->paramb[0]+sd->parame[0]; - sd->paramc[1]=sd->status.agi+sd->paramb[1]+sd->parame[1]; - sd->paramc[2]=sd->status.vit+sd->paramb[2]+sd->parame[2]; - sd->paramc[3]=sd->status.int_+sd->paramb[3]+sd->parame[3]; - sd->paramc[4]=sd->status.dex+sd->paramb[4]+sd->parame[4]; - sd->paramc[5]=sd->status.luk+sd->paramb[5]+sd->parame[5]; - for(i=0;i<6;i++) - if(sd->paramc[i] < 0) sd->paramc[i] = 0; - - if(sd->status.weapon == 11 || sd->status.weapon == 13 || sd->status.weapon == 14) { - str = sd->paramc[4]; - dex = sd->paramc[0]; - } - else { - str = sd->paramc[0]; - dex = sd->paramc[4]; - } - dstr = str/10; - sd->base_atk += str + dstr*dstr + dex/5 + sd->paramc[5]/5; - sd->matk1 += sd->paramc[3]+(sd->paramc[3]/5)*(sd->paramc[3]/5); - sd->matk2 += sd->paramc[3]+(sd->paramc[3]/7)*(sd->paramc[3]/7); - if(sd->matk1 < sd->matk2) { - int temp = sd->matk2; - sd->matk2 = sd->matk1; - sd->matk1 = temp; - } - sd->hit += sd->paramc[4] + sd->status.base_level; - sd->flee += sd->paramc[1] + sd->status.base_level; - sd->def2 += sd->paramc[2]; - sd->mdef2 += sd->paramc[3]; - sd->flee2 += sd->paramc[5]+10; - sd->critical += (sd->paramc[5]*3)+10; - - if(sd->base_atk < 1) - sd->base_atk = 1; - if(sd->critical_rate != 100) - sd->critical = (sd->critical*sd->critical_rate)/100; - if(sd->critical < 10) sd->critical = 10; - if(sd->hit_rate != 100) - sd->hit = (sd->hit*sd->hit_rate)/100; - if(sd->hit < 1) sd->hit = 1; - if(sd->flee_rate != 100) - sd->flee = (sd->flee*sd->flee_rate)/100; - if(sd->flee < 1) sd->flee = 1; - if(sd->flee2_rate != 100) - sd->flee2 = (sd->flee2*sd->flee2_rate)/100; - if(sd->flee2 < 10) sd->flee2 = 10; - if(sd->def_rate != 100) - sd->def = (sd->def*sd->def_rate)/100; - if(sd->def < 0) sd->def = 0; - if(sd->def2_rate != 100) - sd->def2 = (sd->def2*sd->def2_rate)/100; - if(sd->def2 < 1) sd->def2 = 1; - if(sd->mdef_rate != 100) - sd->mdef = (sd->mdef*sd->mdef_rate)/100; - if(sd->mdef < 0) sd->mdef = 0; - if(sd->mdef2_rate != 100) - sd->mdef2 = (sd->mdef2*sd->mdef2_rate)/100; - if(sd->mdef2 < 1) sd->mdef2 = 1; - - // “ñ“—¬ ASPD C³ - if (sd->status.weapon <= 16) - sd->aspd += aspd_base[s_class.job][sd->status.weapon]-(sd->paramc[1]*4+sd->paramc[4])*aspd_base[s_class.job][sd->status.weapon]/1000; - else - sd->aspd += ( - (aspd_base[s_class.job][sd->weapontype1]-(sd->paramc[1]*4+sd->paramc[4])*aspd_base[s_class.job][sd->weapontype1]/1000) + - (aspd_base[s_class.job][sd->weapontype2]-(sd->paramc[1]*4+sd->paramc[4])*aspd_base[s_class.job][sd->weapontype2]/1000) - ) * 140 / 200; - - aspd_rate = sd->aspd_rate; - - //U?‘¬“x?‰Á - - if( (skill=pc_checkskill(sd,AC_VULTURE))>0){ // ƒƒV‚Ì–Ú - sd->hit += skill; - if(sd->status.weapon == 11) - sd->attackrange += skill; - } - - if( (skill=pc_checkskill(sd,BS_WEAPONRESEARCH))>0) // •Ší?‹†‚Ì–½’†—¦?‰Á - sd->hit += skill*2; - if(sd->status.option&2 && (skill = pc_checkskill(sd,RG_TUNNELDRIVE))>0 ) // ƒgƒ“ƒlƒ‹ƒhƒ‰ƒCƒu // ƒgƒ“ƒlƒ‹ƒhƒ‰ƒCƒu - sd->speed += (1.2*DEFAULT_WALK_SPEED - skill*9); - if (pc_iscarton(sd) && (skill=pc_checkskill(sd,MC_PUSHCART))>0) // ƒJ?ƒg‚É‚æ‚鑬“x’ቺ - sd->speed += (10-skill) * (DEFAULT_WALK_SPEED * 0.1); - else if (pc_isriding(sd)) { // ƒyƒRƒyƒR?‚è‚É‚æ‚鑬“x?‰Á - sd->speed -= (0.25 * DEFAULT_WALK_SPEED); - sd->max_weight += 10000; - } - if(sd->sc_count){ - if(sd->sc_data[SC_WINDWALK].timer!=-1) //ƒEƒBƒ“ƒhƒEƒH?ƒNŽž‚ÍLv*2%Œ¸ŽZ - sd->speed -= sd->speed *(sd->sc_data[SC_WINDWALK].val1*2)/100; - if(sd->sc_data[SC_CARTBOOST].timer!=-1) // ƒJ?ƒgƒu?ƒXƒg - sd->speed -= (DEFAULT_WALK_SPEED * 20)/100; - if(sd->sc_data[SC_BERSERK].timer!=-1) //ƒo?ƒT?ƒN’†‚ÍIA‚Æ“¯‚¶‚®‚ç‚¢‘¬‚¢H - sd->speed -= sd->speed *25/100; - if(sd->sc_data[SC_WEDDING].timer!=-1) //Œ‹¥’†‚Í?‚‚Ì‚ª?‚¢ - sd->speed = 2*DEFAULT_WALK_SPEED; - } - - if((skill=pc_checkskill(sd,CR_TRUST))>0) { // ƒtƒFƒCƒX - sd->status.max_hp += skill*200; - sd->subele[6] += skill*5; - } - if((skill=pc_checkskill(sd,BS_SKINTEMPER))>0) - { - sd->subele[0] += skill; - sd->subele[3] += skill*5; - } - - bl=sd->status.base_level; - - sd->status.max_hp += (3500 + bl*hp_coefficient2[s_class.job] + hp_sigma_val[s_class.job][(bl > 0)? bl-1:0])/100 * (100 + sd->paramc[2])/100 + (sd->parame[2] - sd->paramcard[2]); - if (s_class.upper==1) // [MouseJstr] - sd->status.max_hp = sd->status.max_hp * 130/100; - else if (s_class.upper==2) - sd->status.max_hp = sd->status.max_hp * 70/100; - - if(sd->hprate!=100) - sd->status.max_hp = sd->status.max_hp*sd->hprate/100; - - if(sd->sc_data && sd->sc_data[SC_BERSERK].timer!=-1){ // ƒo?ƒT?ƒN - sd->status.max_hp = sd->status.max_hp * 3; - // sd->status.hp = sd->status.hp * 3; - if(sd->status.max_hp > battle_config.max_hp) // removed negative max hp bug by Valaris - sd->status.max_hp = battle_config.max_hp; - if(sd->status.hp > battle_config.max_hp) // removed negative max hp bug by Valaris - sd->status.hp = battle_config.max_hp; - } - if(s_class.job == 23 && sd->status.base_level >= 99){ - sd->status.max_hp = sd->status.max_hp + 2000; - } - - if(sd->status.max_hp > battle_config.max_hp) // removed negative max hp bug by Valaris - sd->status.max_hp = battle_config.max_hp; - if(sd->status.max_hp <= 0) sd->status.max_hp = 1; // end - - // Å‘åSPŒvŽZ - sd->status.max_sp += ((sp_coefficient[s_class.job] * bl) + 1000)/100 * (100 + sd->paramc[3])/100 + (sd->parame[3] - sd->paramcard[3]); - if (s_class.upper==1) // [MouseJstr] - sd->status.max_sp = sd->status.max_sp * 130/100; - else if (s_class.upper==2) - sd->status.max_sp = sd->status.max_sp * 70/100; - if(sd->sprate!=100) - sd->status.max_sp = sd->status.max_sp*sd->sprate/100; - - if((skill=pc_checkskill(sd,HP_MEDITATIO))>0) // ƒƒfƒBƒeƒCƒeƒBƒI - sd->status.max_sp += sd->status.max_sp*skill/100; - if((skill=pc_checkskill(sd,HW_SOULDRAIN))>0) /* ƒ\ƒEƒ‹ƒhƒŒƒCƒ“ */ - sd->status.max_sp += sd->status.max_sp*2*skill/100; - - if(sd->status.max_sp < 0 || sd->status.max_sp > battle_config.max_sp) - sd->status.max_sp = battle_config.max_sp; - - //Ž©‘R‰ñ•œHP - sd->nhealhp = 1 + (sd->paramc[2]/5) + (sd->status.max_hp/200); - if((skill=pc_checkskill(sd,SM_RECOVERY)) > 0) { /* HP‰ñ•œ—ÍŒüã */ - sd->nshealhp = skill*5 + (sd->status.max_hp*skill/500); - if(sd->nshealhp > 0x7fff) sd->nshealhp = 0x7fff; - } - //Ž©‘R‰ñ•œSP - sd->nhealsp = 1 + (sd->paramc[3]/6) + (sd->status.max_sp/100); - if(sd->paramc[3] >= 120) - sd->nhealsp += ((sd->paramc[3]-120)>>1) + 4; - if((skill=pc_checkskill(sd,MG_SRECOVERY)) > 0) { /* SP‰ñ•œ—ÍŒüã */ - sd->nshealsp = skill*3 + (sd->status.max_sp*skill/500); - if(sd->nshealsp > 0x7fff) sd->nshealsp = 0x7fff; - } - - if((skill = pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0) { - sd->nsshealhp = skill*4 + (sd->status.max_hp*skill/500); - sd->nsshealsp = skill*2 + (sd->status.max_sp*skill/500); - if(sd->nsshealhp > 0x7fff) sd->nsshealhp = 0x7fff; - if(sd->nsshealsp > 0x7fff) sd->nsshealsp = 0x7fff; - } - if(sd->hprecov_rate != 100) { - sd->nhealhp = sd->nhealhp*sd->hprecov_rate/100; - if(sd->nhealhp < 1) sd->nhealhp = 1; - } - if(sd->sprecov_rate != 100) { - sd->nhealsp = sd->nhealsp*sd->sprecov_rate/100; - if(sd->nhealsp < 1) sd->nhealsp = 1; - } - /* if((skill=pc_checkskill(sd,HP_MEDITATIO)) > 0) { // f?fffBfefCfefBfI,I'SPR,A*,I',E`,¡©Z((c)¡®R¢¶n~.©«,E',(c),(c),e' - sd->nhealsp += 3*skill*(sd->status.max_sp)/100; - if(sd->nhealsp > 0x7fff) sd->nhealsp = 0x7fff; - } Increase natural SP regen instead of colossal SP Recovery effect [DracoRPG]*/ - - // Ží‘°‘Ï«i‚±‚ê‚Å‚¢‚¢‚ÌH ƒfƒBƒoƒCƒ“ƒvƒƒeƒNƒVƒ‡ƒ“‚Æ“¯‚¶?—‚ª‚¢‚é‚©‚àj - if( (skill=pc_checkskill(sd,SA_DRAGONOLOGY))>0 ){ // ƒhƒ‰ƒSƒmƒƒW? - skill = skill*4; - sd->addrace[9]+=skill; - sd->addrace_[9]+=skill; - sd->subrace[9]+=skill; - sd->magic_addrace[9]+=skill; - sd->magic_subrace[9]-=skill; - } - - //Flee㸠- if( (skill=pc_checkskill(sd,TF_MISS))>0 ){ // ‰ñ”ð—¦?‰Á - if(sd->status.class==6||sd->status.class==4007 || sd->status.class==23){ - sd->flee += skill*3; - } - if(sd->status.class==12||sd->status.class==17||sd->status.class==4013||sd->status.class==4018) - sd->flee += skill*4; - if(sd->status.class==12||sd->status.class==4013) - sd->speed -= sd->speed *(skill*1.5)/100; - } - if( (skill=pc_checkskill(sd,MO_DODGE))>0 ) // Œ©Ø‚è - sd->flee += (skill*3)>>1; - - // ƒXƒLƒ‹‚âƒXƒe?ƒ^ƒXˆÙí‚É‚æ‚é?‚è‚̃pƒ‰ƒ?ƒ^•â³ - if(sd->sc_count){ - // ATK/DEF?‰»Œ` - if(sd->sc_data[SC_ANGELUS].timer!=-1) // ƒGƒ“ƒWƒFƒ‰ƒX - sd->def2 = sd->def2*(110+5*sd->sc_data[SC_ANGELUS].val1)/100; - if(sd->sc_data[SC_IMPOSITIO].timer!=-1) {// ƒCƒ“ƒ|ƒVƒeƒBƒIƒ}ƒkƒX - sd->watk += sd->sc_data[SC_IMPOSITIO].val1*5; - index = sd->equip_index[8]; - if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4) - sd->watk_ += sd->sc_data[SC_IMPOSITIO].val1*5; - } - if(sd->sc_data[SC_PROVOKE].timer!=-1){ // ƒvƒƒ{ƒbƒN - sd->def2 = sd->def2*(100-6*sd->sc_data[SC_PROVOKE].val1)/100; - sd->base_atk = sd->base_atk*(100+2*sd->sc_data[SC_PROVOKE].val1)/100; - sd->watk = sd->watk*(100+2*sd->sc_data[SC_PROVOKE].val1)/100; - index = sd->equip_index[8]; - if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4) - sd->watk_ = sd->watk_*(100+2*sd->sc_data[SC_PROVOKE].val1)/100; - } - if(sd->sc_data[SC_ENDURE].timer!=-1) - sd->mdef2 += sd->sc_data[SC_ENDURE].val1; - if(sd->sc_data[SC_MINDBREAKER].timer!=-1){ // ƒvƒƒ{ƒbƒN - sd->mdef2 = sd->mdef2*(100-6*sd->sc_data[SC_MINDBREAKER].val1)/100; - sd->matk1 = sd->matk1*(100+2*sd->sc_data[SC_MINDBREAKER].val1)/100; - sd->matk2 = sd->matk2*(100+2*sd->sc_data[SC_MINDBREAKER].val1)/100; - } - if(sd->sc_data[SC_POISON].timer!=-1) // “Å?‘Ô - sd->def2 = sd->def2*75/100; - if(sd->sc_data[SC_DRUMBATTLE].timer!=-1){ // ?‘¾ŒÛ‚Ì‹¿‚« - sd->watk += sd->sc_data[SC_DRUMBATTLE].val2; - sd->def += sd->sc_data[SC_DRUMBATTLE].val3; - index = sd->equip_index[8]; - if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4) - sd->watk_ += sd->sc_data[SC_DRUMBATTLE].val2; - } - if(sd->sc_data[SC_NIBELUNGEN].timer!=-1) { // ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö - index = sd->equip_index[9]; - if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 3) - sd->watk += sd->sc_data[SC_NIBELUNGEN].val3; - index = sd->equip_index[8]; - if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 3) - sd->watk_ += sd->sc_data[SC_NIBELUNGEN].val3; - if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4) - sd->watk += sd->sc_data[SC_NIBELUNGEN].val2; - index = sd->equip_index[8]; - if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4) - sd->watk_ += sd->sc_data[SC_NIBELUNGEN].val2; - } - - if(sd->sc_data[SC_VOLCANO].timer!=-1 && sd->def_ele==3){ // ƒ{ƒ‹ƒP?ƒm - sd->watk += sd->sc_data[SC_VIOLENTGALE].val3; - } - - if(sd->sc_data[SC_SIGNUMCRUCIS].timer!=-1) - sd->def = sd->def * (100 - sd->sc_data[SC_SIGNUMCRUCIS].val2)/100; - if(sd->sc_data[SC_ETERNALCHAOS].timer!=-1) // ƒGƒ^?ƒiƒ‹ƒJƒIƒX - sd->def=0; - - if(sd->sc_data[SC_CONCENTRATION].timer!=-1){ //ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ - sd->watk = sd->watk * (100 + 5*sd->sc_data[SC_CONCENTRATION].val1)/100; - index = sd->equip_index[8]; - if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4) - sd->watk_ = sd->watk * (100 + 5*sd->sc_data[SC_CONCENTRATION].val1)/100; - sd->def = sd->def * (100 - 5*sd->sc_data[SC_CONCENTRATION].val1)/100; - } - - if(sd->sc_data[SC_MAGICPOWER].timer!=-1){ //–‚–@—Í?• - sd->matk1 = sd->matk1*(100+5*sd->sc_data[SC_MAGICPOWER].val1)/100; - sd->matk2 = sd->matk2*(100+5*sd->sc_data[SC_MAGICPOWER].val1)/100; - } - if(sd->sc_data[SC_ATKPOT].timer!=-1) - sd->watk += sd->sc_data[SC_ATKPOT].val1; - if(sd->sc_data[SC_MATKPOT].timer!=-1){ - sd->matk1 += sd->sc_data[SC_MATKPOT].val1; - sd->matk2 += sd->sc_data[SC_MATKPOT].val1; - } - - // ASPD/ˆÚ“®‘¬“x?‰»Œn - if(sd->sc_data[SC_TWOHANDQUICKEN].timer != -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) // 2HQ - aspd_rate -= 30; - if(sd->sc_data[SC_ADRENALINE].timer != -1 && sd->sc_data[SC_TWOHANDQUICKEN].timer == -1 && - sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) { // ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… - if(sd->sc_data[SC_ADRENALINE].val2 || !battle_config.party_skill_penaly) - aspd_rate -= 30; - else - aspd_rate -= 25; - } - if(sd->sc_data[SC_SPEARSQUICKEN].timer != -1 && sd->sc_data[SC_ADRENALINE].timer == -1 && - sd->sc_data[SC_TWOHANDQUICKEN].timer == -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) // ƒXƒsƒAƒNƒBƒbƒPƒ“ - aspd_rate -= sd->sc_data[SC_SPEARSQUICKEN].val2; - if(sd->sc_data[SC_ASSNCROS].timer!=-1 && // —[—z‚̃AƒTƒVƒ“ƒNƒƒX - sd->sc_data[SC_TWOHANDQUICKEN].timer==-1 && sd->sc_data[SC_ADRENALINE].timer==-1 && sd->sc_data[SC_SPEARSQUICKEN].timer==-1 && - sd->sc_data[SC_DONTFORGETME].timer == -1) - aspd_rate -= 5+sd->sc_data[SC_ASSNCROS].val1+sd->sc_data[SC_ASSNCROS].val2+sd->sc_data[SC_ASSNCROS].val3; - if(sd->sc_data[SC_DONTFORGETME].timer!=-1){ // Ž„‚ð–Y‚ê‚È‚¢‚Å - aspd_rate += sd->sc_data[SC_DONTFORGETME].val1*3 + sd->sc_data[SC_DONTFORGETME].val2 + (sd->sc_data[SC_DONTFORGETME].val3>>16); - sd->speed= sd->speed*(100+sd->sc_data[SC_DONTFORGETME].val1*2 + sd->sc_data[SC_DONTFORGETME].val2 + (sd->sc_data[SC_DONTFORGETME].val3&0xffff))/100; - } - if( sd->sc_data[i=SC_SPEEDPOTION2].timer!=-1 || - sd->sc_data[i=SC_SPEEDPOTION1].timer!=-1 || - sd->sc_data[i=SC_SPEEDPOTION0].timer!=-1) // ? ‘¬ƒ|?ƒVƒ‡ƒ“ - aspd_rate -= sd->sc_data[i].val2; - - // HIT/FLEE?‰»Œn - if(sd->sc_data[SC_WHISTLE].timer!=-1){ // Œû“J - sd->flee += sd->flee * (sd->sc_data[SC_WHISTLE].val1 - +sd->sc_data[SC_WHISTLE].val2+(sd->sc_data[SC_WHISTLE].val3>>16))/100; - sd->flee2+= (sd->sc_data[SC_WHISTLE].val1+sd->sc_data[SC_WHISTLE].val2+(sd->sc_data[SC_WHISTLE].val3&0xffff)) * 10; - } - if(sd->sc_data[SC_HUMMING].timer!=-1) // ƒnƒ~ƒ“ƒO - sd->hit += (sd->sc_data[SC_HUMMING].val1*2+sd->sc_data[SC_HUMMING].val2 - +sd->sc_data[SC_HUMMING].val3) * sd->hit/100; - if(sd->sc_data[SC_VIOLENTGALE].timer!=-1 && sd->def_ele==4){ // ƒoƒCƒIƒŒƒ“ƒgƒQƒCƒ‹ - sd->flee += sd->flee*sd->sc_data[SC_VIOLENTGALE].val3/100; - } - if(sd->sc_data[SC_BLIND].timer!=-1){ // ˆÃ? - sd->hit -= sd->hit*25/100; - sd->flee -= sd->flee*25/100; - } - if(sd->sc_data[SC_WINDWALK].timer!=-1) // ƒEƒBƒ“ƒhƒEƒH?ƒN - sd->flee += sd->flee*(sd->sc_data[SC_WINDWALK].val2)/100; - if(sd->sc_data[SC_SPIDERWEB].timer!=-1) //ƒXƒpƒCƒ_?ƒEƒFƒu - sd->flee -= sd->flee*50/100; - if(sd->sc_data[SC_TRUESIGHT].timer!=-1) //ƒgƒDƒ‹?ƒTƒCƒg - sd->hit += 3*(sd->sc_data[SC_TRUESIGHT].val1); - if(sd->sc_data[SC_CONCENTRATION].timer!=-1) //ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ - sd->hit += (10*(sd->sc_data[SC_CONCENTRATION].val1)); - - // ‘Ï« - if(sd->sc_data[SC_SIEGFRIED].timer!=-1){ // •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh - sd->subele[1] += sd->sc_data[SC_SIEGFRIED].val2; // … - sd->subele[2] += sd->sc_data[SC_SIEGFRIED].val2; // … - sd->subele[3] += sd->sc_data[SC_SIEGFRIED].val2; // ‰Î - sd->subele[4] += sd->sc_data[SC_SIEGFRIED].val2; // … - sd->subele[5] += sd->sc_data[SC_SIEGFRIED].val2; // … - sd->subele[6] += sd->sc_data[SC_SIEGFRIED].val2; // … - sd->subele[7] += sd->sc_data[SC_SIEGFRIED].val2; // … - sd->subele[8] += sd->sc_data[SC_SIEGFRIED].val2; // … - sd->subele[9] += sd->sc_data[SC_SIEGFRIED].val2; // … - } - if(sd->sc_data[SC_PROVIDENCE].timer!=-1){ // ƒvƒƒ”ƒBƒfƒ“ƒX - sd->subele[6] += sd->sc_data[SC_PROVIDENCE].val2; // ? ¹?« - sd->subrace[6] += sd->sc_data[SC_PROVIDENCE].val2; // ? ?–‚ - } - - // ‚»‚Ì‘¼ - if(sd->sc_data[SC_APPLEIDUN].timer!=-1){ // ƒCƒhƒDƒ“‚Ì—ÑŒç - sd->status.max_hp += ((5+sd->sc_data[SC_APPLEIDUN].val1*2+((sd->sc_data[SC_APPLEIDUN].val2+1)>>1) - +sd->sc_data[SC_APPLEIDUN].val3/10) * sd->status.max_hp)/100; - if(sd->status.max_hp < 0 || sd->status.max_hp > battle_config.max_hp) - sd->status.max_hp = battle_config.max_hp; - } - if(sd->sc_data[SC_DELUGE].timer!=-1 && sd->def_ele==1){ // ƒfƒŠƒ…?ƒW - sd->status.max_hp += sd->status.max_hp*sd->sc_data[SC_DELUGE].val3/100; - if(sd->status.max_hp < 0 || sd->status.max_hp > battle_config.max_hp) - sd->status.max_hp = battle_config.max_hp; - } - if(sd->sc_data[SC_SERVICE4U].timer!=-1) { // ƒT?ƒrƒXƒtƒH?ƒ†? - sd->status.max_sp += sd->status.max_sp*(10+sd->sc_data[SC_SERVICE4U].val1+sd->sc_data[SC_SERVICE4U].val2 - +sd->sc_data[SC_SERVICE4U].val3)/100; - if(sd->status.max_sp < 0 || sd->status.max_sp > battle_config.max_sp) - sd->status.max_sp = battle_config.max_sp; - sd->dsprate-=(10+sd->sc_data[SC_SERVICE4U].val1*3+sd->sc_data[SC_SERVICE4U].val2 - +sd->sc_data[SC_SERVICE4U].val3); - if(sd->dsprate<0)sd->dsprate=0; - } - - if(sd->sc_data[SC_FORTUNE].timer!=-1) // K‰^‚̃LƒX - sd->critical += (10+sd->sc_data[SC_FORTUNE].val1+sd->sc_data[SC_FORTUNE].val2 - +sd->sc_data[SC_FORTUNE].val3)*10; - - if(sd->sc_data[SC_EXPLOSIONSPIRITS].timer!=-1){ // ”š—ô”g“® - if(s_class.job==23) - sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val1*100; - else - sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val2; - } - - if(sd->sc_data[SC_STEELBODY].timer!=-1){ // ‹à„ - sd->def = 90; - sd->mdef = 90; - aspd_rate += 25; - sd->speed = (sd->speed * 125) / 100; - } - if(sd->sc_data[SC_DEFENDER].timer != -1) { - sd->aspd += (550 - sd->sc_data[SC_DEFENDER].val1*50); - sd->speed = (sd->speed * (155 - sd->sc_data[SC_DEFENDER].val1*5)) / 100; - } - if(sd->sc_data[SC_ENCPOISON].timer != -1) - sd->addeff[4] += sd->sc_data[SC_ENCPOISON].val2; - - if( sd->sc_data[SC_DANCING].timer!=-1 ){ // ‰‰‘t/ƒ_ƒ“ƒXŽg—p’† - sd->speed*=4; - sd->nhealsp = 0; - sd->nshealsp = 0; - sd->nsshealsp = 0; - } - if(sd->sc_data[SC_CURSE].timer!=-1) - sd->speed += 450; - - if(sd->sc_data[SC_TRUESIGHT].timer!=-1) //ƒgƒDƒ‹?ƒTƒCƒg - sd->critical += sd->critical*(sd->sc_data[SC_TRUESIGHT].val1)/100; - -/* if(sd->sc_data[SC_VOLCANO].timer!=-1) // ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“(?«‚Íbattle.c‚Å) - sd->addeff[2]+=sd->sc_data[SC_VOLCANO].val2;//% of granting - if(sd->sc_data[SC_DELUGE].timer!=-1) // ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“(?«‚Íbattle.c‚Å) - sd->addeff[0]+=sd->sc_data[SC_DELUGE].val2;//% of granting - */ - if(sd->sc_data[SC_BERSERK].timer!=-1) { //All Def/MDef reduced to 0 while in Berserk [DracoRPG] - sd->def = sd->def2 = 0; - sd->mdef = sd->mdef2 = 0; - sd->flee -= sd->flee*50/100; - aspd_rate -= 30; - //sd->base_atk *= 3; - } - if(sd->sc_data[SC_KEEPING].timer!=-1) - sd->def = 100; - if(sd->sc_data[SC_BARRIER].timer!=-1) - sd->mdef = 100; - } - - if(sd->speed_rate != 100) - sd->speed = sd->speed*sd->speed_rate/100; - if(sd->speed < 1) sd->speed = 1; - if(aspd_rate != 100) - sd->aspd = sd->aspd*aspd_rate/100; - if(pc_isriding(sd)) // ‹R•ºC—û - sd->aspd = sd->aspd*(100 + 10*(5 - pc_checkskill(sd,KN_CAVALIERMASTERY)))/ 100; - if(sd->aspd < battle_config.max_aspd) sd->aspd = battle_config.max_aspd; - sd->amotion = sd->aspd; - sd->dmotion = 800-sd->paramc[1]*4; - if(sd->dmotion<400) - sd->dmotion = 400; - if(sd->skilltimer != -1 && (skill = pc_checkskill(sd,SA_FREECAST)) > 0) { - sd->prev_speed = sd->speed; - sd->speed = sd->speed*(175 - skill*5)/100; - } - - if(sd->status.hp>sd->status.max_hp) - sd->status.hp=sd->status.max_hp; - if(sd->status.sp>sd->status.max_sp) - sd->status.sp=sd->status.max_sp; - - if(first&4) - return 0; - if(first&3) { - clif_updatestatus(sd,SP_SPEED); - clif_updatestatus(sd,SP_MAXHP); - clif_updatestatus(sd,SP_MAXSP); - if(first&1) { - clif_updatestatus(sd,SP_HP); - clif_updatestatus(sd,SP_SP); - } - return 0; - } - - if(b_class != sd->view_class) { - clif_changelook(&sd->bl,LOOK_BASE,sd->view_class); -#if PACKETVER < 4 - clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); - clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); -#else - clif_changelook(&sd->bl,LOOK_WEAPON,0); -#endif - } - - if( memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill)) || b_attackrange != sd->attackrange) - clif_skillinfoblock(sd); // ƒXƒLƒ‹‘—M - - if(b_speed != sd->speed) - clif_updatestatus(sd,SP_SPEED); - if(b_weight != sd->weight) - clif_updatestatus(sd,SP_WEIGHT); - if(b_max_weight != sd->max_weight) { - clif_updatestatus(sd,SP_MAXWEIGHT); - pc_checkweighticon(sd); - } - for(i=0;i<6;i++) - if(b_paramb[i] + b_parame[i] != sd->paramb[i] + sd->parame[i]) - clif_updatestatus(sd,SP_STR+i); - if(b_hit != sd->hit) - clif_updatestatus(sd,SP_HIT); - if(b_flee != sd->flee) - clif_updatestatus(sd,SP_FLEE1); - if(b_aspd != sd->aspd) - clif_updatestatus(sd,SP_ASPD); - if(b_watk != sd->watk || b_base_atk != sd->base_atk) - clif_updatestatus(sd,SP_ATK1); - if(b_def != sd->def) - clif_updatestatus(sd,SP_DEF1); - if(b_watk2 != sd->watk2) - clif_updatestatus(sd,SP_ATK2); - if(b_def2 != sd->def2) - clif_updatestatus(sd,SP_DEF2); - if(b_flee2 != sd->flee2) - clif_updatestatus(sd,SP_FLEE2); - if(b_critical != sd->critical) - clif_updatestatus(sd,SP_CRITICAL); - if(b_matk1 != sd->matk1) - clif_updatestatus(sd,SP_MATK1); - if(b_matk2 != sd->matk2) - clif_updatestatus(sd,SP_MATK2); - if(b_mdef != sd->mdef) - clif_updatestatus(sd,SP_MDEF1); - if(b_mdef2 != sd->mdef2) - clif_updatestatus(sd,SP_MDEF2); - if(b_attackrange != sd->attackrange) - clif_updatestatus(sd,SP_ATTACKRANGE); - if(b_max_hp != sd->status.max_hp) - clif_updatestatus(sd,SP_MAXHP); - if(b_max_sp != sd->status.max_sp) - clif_updatestatus(sd,SP_MAXSP); - if(b_hp != sd->status.hp) - clif_updatestatus(sd,SP_HP); - if(b_sp != sd->status.sp) - clif_updatestatus(sd,SP_SP); - -/* if(before.cart_num != before.cart_num || before.cart_max_num != before.cart_max_num || - before.cart_weight != before.cart_weight || before.cart_max_weight != before.cart_max_weight ) - clif_updatestatus(sd,SP_CARTINFO);*/ - - if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 && - (sd->sc_data[SC_PROVOKE].timer==-1 || sd->sc_data[SC_PROVOKE].val2==0 ) && !pc_isdead(sd)) - // ƒI?ƒgƒo?ƒT?ƒN?“® - skill_status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0); - - return 0; -} - -/*========================================== - * For quick calculating [Celest] - *------------------------------------------ - */ -int pc_calcspeed (struct map_session_data *sd) -{ - int b_speed, skill; - struct pc_base_job s_class; - - nullpo_retr(0, sd); - - s_class = pc_calc_base_job(sd->status.class); - - b_speed = sd->speed; - sd->speed = DEFAULT_WALK_SPEED ; - - if(sd->sc_count){ - if(sd->sc_data[SC_INCREASEAGI].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1){ // ‘¬“x?‰Á - sd->speed -= sd->speed *25/100; - } - if(sd->sc_data[SC_DECREASEAGI].timer!=-1) { - sd->speed = sd->speed *125/100; - } - if(sd->sc_data[SC_CLOAKING].timer!=-1) { - sd->speed = sd->speed * (sd->sc_data[SC_CLOAKING].val3-sd->sc_data[SC_CLOAKING].val1*3) /100; - } - if(sd->sc_data[SC_CHASEWALK].timer!=-1) { - sd->speed = sd->speed * sd->sc_data[SC_CHASEWALK].val3 /100; - } - if(sd->sc_data[SC_QUAGMIRE].timer!=-1){ - sd->speed = sd->speed*3/2; - } - if(sd->sc_data[SC_WINDWALK].timer!=-1) { - sd->speed -= sd->speed *(sd->sc_data[SC_WINDWALK].val1*2)/100; - } - if(sd->sc_data[SC_CARTBOOST].timer!=-1) { - sd->speed -= (DEFAULT_WALK_SPEED * 20)/100; - } - if(sd->sc_data[SC_BERSERK].timer!=-1) { - sd->speed -= sd->speed *25/100; - } - if(sd->sc_data[SC_WEDDING].timer!=-1) { - sd->speed = 2*DEFAULT_WALK_SPEED; - } - if(sd->sc_data[SC_DONTFORGETME].timer!=-1){ - sd->speed= sd->speed*(100+sd->sc_data[SC_DONTFORGETME].val1*2 + sd->sc_data[SC_DONTFORGETME].val2 + (sd->sc_data[SC_DONTFORGETME].val3&0xffff))/100; - } - if(sd->sc_data[SC_STEELBODY].timer!=-1){ - sd->speed = (sd->speed * 125) / 100; - } - if(sd->sc_data[SC_DEFENDER].timer != -1) { - sd->speed = (sd->speed * (155 - sd->sc_data[SC_DEFENDER].val1*5)) / 100; - } - if( sd->sc_data[SC_DANCING].timer!=-1 ){ - sd->speed*=4; - } - if(sd->sc_data[SC_CURSE].timer!=-1) - sd->speed += 450; - } - - if(sd->status.option&2 && (skill = pc_checkskill(sd,RG_TUNNELDRIVE))>0 ) - sd->speed += (1.2*DEFAULT_WALK_SPEED - skill*9); - if (pc_iscarton(sd) && (skill=pc_checkskill(sd,MC_PUSHCART))>0) - sd->speed += (10-skill) * (DEFAULT_WALK_SPEED * 0.1); - else if (pc_isriding(sd)) { - sd->speed -= (0.25 * DEFAULT_WALK_SPEED); - } - if((skill=pc_checkskill(sd,TF_MISS))>0) - if(s_class.job==12) - sd->speed -= sd->speed *(skill*1.5)/100; - - if(sd->speed_rate != 100) - sd->speed = sd->speed*sd->speed_rate/100; - if(sd->speed < 1) sd->speed = 1; - - if(sd->skilltimer != -1 && (skill = pc_checkskill(sd,SA_FREECAST)) > 0) { - sd->prev_speed = sd->speed; - sd->speed = sd->speed*(175 - skill*5)/100; - } - - if(b_speed != sd->speed) - clif_updatestatus(sd,SP_SPEED); - - return 0; -} - -/*========================================== * ? ”õ•i‚É‚æ‚é”\—Í“™‚̃{?ƒiƒXÝ’è *------------------------------------------ */ int pc_bonus(struct map_session_data *sd,int type,int val) { + int i; nullpo_retr(0, sd); switch(type){ @@ -2523,20 +1488,12 @@ int pc_bonus(struct map_session_data *sd,int type,int val) sd->parame[SP_INT-SP_STR]+=val; sd->parame[SP_DEX-SP_STR]+=val; sd->parame[SP_LUK-SP_STR]+=val; - clif_updatestatus(sd,13); - clif_updatestatus(sd,14); - clif_updatestatus(sd,15); - clif_updatestatus(sd,16); - clif_updatestatus(sd,17); - clif_updatestatus(sd,18); } break; case SP_AGI_VIT: // [Valaris] if(sd->state.lr_flag!=2) { sd->parame[SP_AGI-SP_STR]+=val; sd->parame[SP_VIT-SP_STR]+=val; - clif_updatestatus(sd,14); - clif_updatestatus(sd,15); } break; case SP_AGI_DEX_STR: // [Valaris] @@ -2544,9 +1501,6 @@ int pc_bonus(struct map_session_data *sd,int type,int val) sd->parame[SP_AGI-SP_STR]+=val; sd->parame[SP_DEX-SP_STR]+=val; sd->parame[SP_STR-SP_STR]+=val; - clif_updatestatus(sd,14); - clif_updatestatus(sd,17); - clif_updatestatus(sd,13); } break; case SP_PERFECT_HIDE: // [Valaris] @@ -2570,11 +1524,106 @@ int pc_bonus(struct map_session_data *sd,int type,int val) sd->unbreakable += val; } break; + case SP_UNBREAKABLE_WEAPON: + if(sd->state.lr_flag != 2) + sd->unbreakable_equip |= EQP_WEAPON; + break; + case SP_UNBREAKABLE_ARMOR: + if(sd->state.lr_flag != 2) + sd->unbreakable_equip |= EQP_ARMOR; + break; + case SP_UNBREAKABLE_HELM: + if(sd->state.lr_flag != 2) + sd->unbreakable_equip |= EQP_HELM; + break; + case SP_UNBREAKABLE_SHIELD: + if(sd->state.lr_flag != 2) + sd->unbreakable_equip |= EQP_SHIELD; + break; case SP_CLASSCHANGE: // [Valaris] if(sd->state.lr_flag !=2){ sd->classchange=val; } break; + case SP_LONG_ATK_RATE: + if(sd->status.weapon == 11 && sd->state.lr_flag != 2) + sd->atk_rate += val; + break; + case SP_BREAK_WEAPON_RATE: + if(sd->state.lr_flag != 2) + sd->break_weapon_rate+=val; + break; + case SP_BREAK_ARMOR_RATE: + if(sd->state.lr_flag != 2) + sd->break_armor_rate+=val; + break; + case SP_ADD_STEAL_RATE: + if(sd->state.lr_flag != 2) + sd->add_steal_rate+=val; + break; + case SP_DELAYRATE: + if(sd->state.lr_flag != 2) + sd->delayrate+=val; + break; + case SP_CRIT_ATK_RATE: + if(sd->state.lr_flag != 2) + sd->crit_atk_rate += val; + break; + case SP_NO_REGEN: + if(sd->state.lr_flag != 2) + sd->no_regen = val; + break; + case SP_UNSTRIPABLE_WEAPON: + if(sd->state.lr_flag != 2) + sd->unstripable_equip |= EQP_WEAPON; + break; + case SP_UNSTRIPABLE: + case SP_UNSTRIPABLE_ARMOR: + if(sd->state.lr_flag != 2) + sd->unstripable_equip |= EQP_ARMOR; + break; + case SP_UNSTRIPABLE_HELM: + if(sd->state.lr_flag != 2) + sd->unstripable_equip |= EQP_HELM; + break; + case SP_UNSTRIPABLE_SHIELD: + if(sd->state.lr_flag != 2) + sd->unstripable_equip |= EQP_SHIELD; + break; + case SP_SP_GAIN_VALUE: + if(!sd->state.lr_flag) + sd->sp_gain_value += val; + break; + case SP_IGNORE_DEF_MOB: // 0:normal monsters only, 1:affects boss monsters as well + if(!sd->state.lr_flag) + sd->ignore_def_mob |= 1<<val; + else if(sd->state.lr_flag == 1) + sd->ignore_def_mob_ |= 1<<val; + break; + case SP_HP_GAIN_VALUE: + if(!sd->state.lr_flag) + sd->hp_gain_value += val; + break; + case SP_DAMAGE_WHEN_UNEQUIP: + if(!sd->state.lr_flag) { + for (i=0; i<11; i++) { + if (sd->inventory_data[current_equip_item_index]->equip & equip_pos[i]) { + sd->unequip_losehp[i] += val; + break; + } + } + } + break; + case SP_LOSESP_WHEN_UNEQUIP: + if(!sd->state.lr_flag) { + for (i=0; i<11; i++) { + if (sd->inventory_data[current_equip_item_index]->equip & equip_pos[i]) { + sd->unequip_losesp[i] += val; + break; + } + } + } + break; default: if(battle_config.error_log) printf("pc_bonus: unknown type %d %d !\n",type,val); @@ -2754,8 +1803,9 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) } else if(sd->state.lr_flag == 1) { sd->sp_drain_rate_ += type2; - sd->sp_drain_per_ += val; + sd->sp_drain_per_ += val; } + sd->sp_drain_type = 0; break; case SP_SP_DRAIN_VALUE: if(!sd->state.lr_flag) { @@ -2766,7 +1816,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->sp_drain_rate_ += type2; sd->sp_drain_value_ += val; } - + sd->sp_drain_type = 0; break; case SP_WEAPON_COMA_ELE: if(sd->state.lr_flag != 2) @@ -2780,8 +1830,92 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) if(sd->state.lr_flag !=2){ sd->random_attack_increase_add = type2; sd->random_attack_increase_per += val; - } + } + break; + case SP_WEAPON_ATK: + if(sd->state.lr_flag != 2) + sd->weapon_atk[type2]+=val; + break; + case SP_WEAPON_ATK_RATE: + if(sd->state.lr_flag != 2) + sd->weapon_atk_rate[type2]+=val; + break; + case SP_CRITICAL_ADDRACE: + if(sd->state.lr_flag != 2) + sd->critaddrace[type2]+=val; + break; + case SP_ADDEFF_WHENHIT: + if(sd->state.lr_flag != 2) { + sd->addeff3[type2]+=val; + sd->addeff3_type[type2]=1; + } break; + case SP_ADDEFF_WHENHIT_SHORT: + if(sd->state.lr_flag != 2) { + sd->addeff3[type2]+=val; + sd->addeff3_type[type2]=0; + } + break; + case SP_SKILL_ATK: + if(sd->state.lr_flag != 2) { + if (sd->skillatk[0] == type2) + sd->skillatk[1] += val; + else { + sd->skillatk[0] = type2; + sd->skillatk[1] = val; + } + } + break; + case SP_ADD_DAMAGE_BY_CLASS: + if(sd->state.lr_flag != 2) { + for(i=0;i<sd->add_damage_class_count2;i++) { + if(sd->add_damage_classid2[i] == type2) { + sd->add_damage_classrate2[i] += val; + break; + } + } + if(i >= sd->add_damage_class_count2 && sd->add_damage_class_count2 < 10) { + sd->add_damage_classid2[sd->add_damage_class_count2] = type2; + sd->add_damage_classrate2[sd->add_damage_class_count2] += val; + sd->add_damage_class_count2++; + } + } + break; + case SP_HP_LOSS_RATE: + if(sd->state.lr_flag != 2) { + sd->hp_loss_value = type2; + sd->hp_loss_rate = val; + } + break; + case SP_ADDRACE2: + if (type2 > 0 && type2 < MAX_MOB_RACE_DB) + break; + if(sd->state.lr_flag != 2) + sd->addrace2[type2] += val; + else + sd->addrace2_[type2] += val; + break; + case SP_SUBSIZE: + if(sd->state.lr_flag != 2) + sd->subsize[type2]+=val; + break; + case SP_SUBRACE2: + if(sd->state.lr_flag != 2) + sd->subrace2[type2]+=val; + break; + case SP_ADD_ITEM_HEAL_RATE: + if(sd->state.lr_flag != 2) + sd->itemhealrate[type2 - 1] += val; + break; + case SP_EXP_ADDRACE: + if(sd->state.lr_flag != 2) + sd->expaddrace[type2]+=val; + break; + case SP_SP_GAIN_RACE: + if(sd->state.lr_flag != 2) + sd->sp_gain_race[type2]+=val; + break; + default: if(battle_config.error_log) printf("pc_bonus2: unknown type %d %d %d!\n",type,type2,val); @@ -2819,6 +1953,42 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) sd->autospell_rate = val; } break; + case SP_AUTOSPELL_WHENHIT: + if(sd->state.lr_flag != 2){ + sd->autospell2_id = type2; + sd->autospell2_lv = type3; + sd->autospell2_rate = val; + sd->autospell2_type = 1; // enemy + } + break; + case SP_HP_LOSS_RATE: + if(sd->state.lr_flag != 2) { + sd->hp_loss_value = type2; + sd->hp_loss_rate = type3; + sd->hp_loss_type = val; + } + break; + case SP_SP_DRAIN_RATE: + if(!sd->state.lr_flag) { + sd->sp_drain_rate += type2; + sd->sp_drain_per += type3; + } + else if(sd->state.lr_flag == 1) { + sd->sp_drain_rate_ += type2; + sd->sp_drain_per_ += type3; + } + sd->sp_drain_type = val; + break; + case SP_SP_DRAIN_VALUE: + if(!sd->state.lr_flag) { + sd->sp_drain_rate += type2; + sd->sp_drain_value += type3; + } + else if(sd->state.lr_flag == 1) { + sd->sp_drain_rate_ += type2; + sd->sp_drain_value_ += type3; + } + sd->sp_drain_type = val; default: if(battle_config.error_log) printf("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val); @@ -2828,6 +1998,26 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) return 0; } +int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4,int val) +{ + switch(type){ + case SP_AUTOSPELL_WHENHIT: + if(sd->state.lr_flag != 2){ + sd->autospell2_id = type2; + sd->autospell2_lv = type3; + sd->autospell2_rate = type4; + sd->autospell2_type = val; // 0: self, 1: enemy + } + break; + default: + if(battle_config.error_log) + printf("pc_bonus4: unknown type %d %d %d %d %d!\n",type,type2,type3,type4,val); + break; + } + + return 0; +} + /*========================================== * ƒXƒNƒŠƒvƒg‚É‚æ‚éƒXƒLƒ‹Š“¾ *------------------------------------------ @@ -2843,12 +2033,12 @@ int pc_skill(struct map_session_data *sd,int id,int level,int flag) } if(!flag && (sd->status.skill[id].id == id || level == 0)){ // ƒNƒGƒXƒgŠ“¾‚Ȃ炱‚±‚Å?Œ‚ðŠm”F‚µ‚Ä‘—M‚·‚é sd->status.skill[id].lv=level; - pc_calcstatus(sd,0); + status_calc_pc(sd,0); clif_skillinfoblock(sd); } else if(flag==2 && (sd->status.skill[id].id == id || level == 0)){ // ƒNƒGƒXƒgŠ“¾‚Ȃ炱‚±‚Å?Œ‚ðŠm”F‚µ‚Ä‘—M‚·‚é sd->status.skill[id].lv+=level; - pc_calcstatus(sd,0); + status_calc_pc(sd,0); clif_skillinfoblock(sd); } else if(sd->status.skill[id].lv < level){ // ?‚¦‚ç‚ê‚邪lv‚ª¬‚³‚¢‚È‚ç @@ -2865,6 +2055,32 @@ int pc_skill(struct map_session_data *sd,int id,int level,int flag) } /*========================================== + * + *------------------------------------------ + */ +int pc_blockskill_end(int tid,unsigned int tick,int id,int data) +{ + struct map_session_data *sd = map_id2sd(id); + if (data <= 0 || data >= MAX_SKILL) + return 0; + if (sd) sd->blockskill[data] = 0; + + return 1; +} +int pc_blockskill_start (struct map_session_data *sd, int skillid, int tick) +{ + nullpo_retr (-1, sd); + + if (skillid >= 10000 && skillid < 10015) + skillid -= 9500; + else if (skillid < 1 || skillid > MAX_SKILL) + return -1; + + sd->blockskill[skillid] = 1; + return add_timer(gettick()+tick,pc_blockskill_end,sd->bl.id,skillid); +} + +/*========================================== * ƒJ?ƒh?“ü *------------------------------------------ */ @@ -2950,7 +2166,7 @@ int pc_modifysellvalue(struct map_session_data *sd,int orig_value) } /*========================================== - * ƒAƒCƒeƒ€‚𔃂Á‚½Žž‚ÉAV‚µ‚¢ƒAƒCƒeƒ€—“‚ðŽg‚¤‚©A + * ƒAƒCƒeƒ€‚𔃂Á‚½ŽbÉAV‚µ‚¢ƒAƒCƒeƒ€—“‚ðŽg‚¤‚©A * 3–œŒÂ§ŒÀ‚É‚©‚©‚é‚©Šm”F *------------------------------------------ */ @@ -3074,7 +2290,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount) i = MAX_INVENTORY; if(!itemdb_isequip2(data)){ - // ? ”õ•i‚ł͂Ȃ¢‚Ì‚ÅA?Š—L•i‚È‚çŒÂ?‚Ì‚Ý?‰»‚³‚¹‚é + // ‘• ”õ•i‚ł͂Ȃ¢‚Ì‚ÅAŠùŠ—L•i‚È‚çŒÂ”‚̂ݕω»‚³‚¹‚é for(i=0;i<MAX_INVENTORY;i++) if(sd->status.inventory[i].nameid == item_data->nameid && sd->status.inventory[i].card[0] == item_data->card[0] && sd->status.inventory[i].card[1] == item_data->card[1] && @@ -3087,7 +2303,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount) } } if(i >= MAX_INVENTORY){ - // ? ”õ•i‚©–¢Š—L•i‚¾‚Á‚½‚̂ŋ󂫗“‚֒ljÁ + // ‘• ”õ•i‚©–¢Š—L•i‚¾‚Á‚½‚̂ŋ󂫗“‚֒ljÁ i = pc_search_inventory(sd,0); if(i >= 0) { memcpy(&sd->status.inventory[i],item_data,sizeof(sd->status.inventory[0])); @@ -3118,7 +2334,7 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type) sd->weight -= sd->inventory_data[n]->weight*amount ; if(sd->status.inventory[n].amount<=0){ if(sd->status.inventory[n].equip) - pc_unequipitem(sd,n,0,BF_NORMAL); + pc_unequipitem(sd,n,3); memset(&sd->status.inventory[n],0,sizeof(sd->status.inventory[0])); sd->inventory_data[n] = NULL; } @@ -3139,19 +2355,17 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount) nullpo_retr(1, sd); if(n < 0 || n >= MAX_INVENTORY) - return 1; - if(amount <= 0) - return 1; - if (sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount < amount || sd->trade_partner != 0 || sd->vender_id != 0 || - sd->status.inventory[n].amount <= 0) + sd->status.inventory[n].amount <= 0 || + itemdb_isdropable(sd->status.inventory[n].nameid) == 0 || // Celest + pc_candrop(sd,sd->status.inventory[n].nameid)) return 1; map_addflooritem(&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, NULL, NULL, NULL, 0); pc_delitem(sd, n, amount, 0); @@ -3227,6 +2441,8 @@ int pc_isUseitem(struct map_session_data *sd,int n) if(item == NULL) return 0; + if(item->type != 0 && item->type != 2) + return 0; if((nameid == 605) && map[sd->bl.m].flag.gvg) return 0; if(nameid == 601 && (map[sd->bl.m].flag.noteleport || map[sd->bl.m].flag.gvg)) { @@ -3241,18 +2457,16 @@ int pc_isUseitem(struct map_session_data *sd,int n) return 0; if(item->elv > 0 && sd->status.base_level < item->elv) return 0; - if(((sd->status.class==13 || sd->status.class==4014) && ((1<<7)&item->class) == 0) || // have mounted classes use unmounted items [Valaris] - ((sd->status.class==21 || sd->status.class==4022) && ((1<<14)&item->class) == 0)) + if(((sd->status.class_==13 || sd->status.class_==4014) && ((1<<7)&item->class_) == 0) || // have mounted classes use unmounted items [Valaris] + ((sd->status.class_==21 || sd->status.class_==4022) && ((1<<14)&item->class_) == 0)) return 0; - if(sd->status.class!=13 && sd->status.class!=4014 && sd->status.class!=21 && sd->status.class!=4022) - if((sd->status.class<=4000 && ((1<<sd->status.class)&item->class) == 0) || (sd->status.class>4000 && sd->status.class<4023 && ((1<<(sd->status.class-4001))&item->class) == 0) || - (sd->status.class>=4023 && ((1<<(sd->status.class-4023))&item->class) == 0)) + if(sd->status.class_!=13 && sd->status.class_!=4014 && sd->status.class_!=21 && sd->status.class_!=4022) + if((sd->status.class_<=4000 && ((1<<sd->status.class_)&item->class_) == 0) || (sd->status.class_>4000 && sd->status.class_<4023 && ((1<<(sd->status.class_-4001))&item->class_) == 0) || + (sd->status.class_>=4023 && ((1<<(sd->status.class_-4023))&item->class_) == 0)) return 0; -#ifndef TXT_ONLY if((log_config.branch > 0) && (nameid == 604)) log_branch(sd); -#endif return 1; } @@ -3263,28 +2477,31 @@ int pc_isUseitem(struct map_session_data *sd,int n) */ int pc_useitem(struct map_session_data *sd,int n) { - int nameid,amount; + int amount; nullpo_retr(1, sd); if(n >=0 && n < MAX_INVENTORY) { - nameid = sd->status.inventory[n].nameid; + char *script; + sd->itemid = sd->status.inventory[n].nameid; amount = sd->status.inventory[n].amount; if(sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 0 || sd->sc_data[SC_BERSERK].timer!=-1 || sd->sc_data[SC_MARIONETTE].timer!=-1 || + (pc_issit(sd) && (sd->itemid == 605 || sd->itemid == 606)) || + //added item_noequip.txt items check by Maya&[Lupus] + (map[sd->bl.m].flag.pvp && (sd->inventory_data[n]->flag.no_equip&1) ) || // PVP + (map[sd->bl.m].flag.gvg && (sd->inventory_data[n]->flag.no_equip>1) ) || // GVG !pc_isUseitem(sd,n) ) { clif_useitemack(sd,n,0,0); return 1; } - if(sd->inventory_data[n]) - run_script(sd->inventory_data[n]->use_script,0,sd->bl.id,0); - - pc_delitem(sd,n,1,1); + script = sd->inventory_data[n]->use_script; amount = sd->status.inventory[n].amount; - - clif_useitemack(sd,n,amount,1); + clif_useitemack(sd,n,amount-1,1); + run_script(script,0,sd->bl.id,0); + pc_delitem(sd,n,1,1); } return 0; @@ -3311,7 +2528,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun i=MAX_CART; if(!itemdb_isequip2(data)){ - // ? ”õ•i‚ł͂Ȃ¢‚Ì‚ÅA?Š—L•i‚È‚çŒÂ?‚Ì‚Ý?‰»‚³‚¹‚é + // ‘• ”õ•i‚ł͂Ȃ¢‚Ì‚ÅAŠùŠ—L•i‚È‚çŒÂ”‚̂ݕω»‚³‚¹‚é for(i=0;i<MAX_CART;i++){ if(sd->status.cart[i].nameid==item_data->nameid && sd->status.cart[i].card[0] == item_data->card[0] && sd->status.cart[i].card[1] == item_data->card[1] && @@ -3325,7 +2542,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun } } if(i >= MAX_CART){ - // ? ”õ•i‚©–¢Š—L•i‚¾‚Á‚½‚̂ŋ󂫗“‚֒ljÁ + // ‘• ”õ•i‚©–¢Š—L•i‚¾‚Á‚½‚̂ŋ󂫗“‚֒ljÁ for(i=0;i<MAX_CART;i++){ if(sd->status.cart[i].nameid==0){ memcpy(&sd->status.cart[i],item_data,sizeof(sd->status.cart[0])); @@ -3380,6 +2597,10 @@ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount) { nullpo_retr(0, sd); nullpo_retr(0, item_data = &sd->status.inventory[idx]); + if(itemdb_isdropable(sd->status.inventory[idx].nameid) == 0) + return 1; + if(pc_candrop(sd,sd->status.inventory[idx].nameid)==1) + return 1; if (item_data->nameid==0 || item_data->amount<amount || sd->vender_id) return 1; if (pc_cart_additem(sd,item_data,amount) == 0) @@ -3460,18 +2681,31 @@ int pc_item_identify(struct map_session_data *sd,int idx) */ int pc_item_repair(struct map_session_data *sd,int idx) { - int flag=1; + int flag=1, material; + int materials[5] = { 0, 1002, 998, 999, 756 }; + struct item *item; nullpo_retr(0, sd); + item = &sd->status.inventory[idx]; + if(idx >= 0 && idx < MAX_INVENTORY) { - if(sd->status.inventory[idx].nameid > 0 && sd->status.inventory[idx].attribute == 1 ) { + if(item->nameid > 0 && item->attribute == 1 ) { + if (itemdb_type(item->nameid)==4) + material = materials [itemdb_wlv (item->nameid)]; + else + material = materials [3]; + + if (pc_search_inventory(sd, material) < 0 ) { //fixed by Lupus (item pos can be = 0!) + clif_skill_fail(sd,sd->skillid,0,0); + return 0; + } flag=0; - sd->status.inventory[idx].attribute=0; + item->attribute=0; //Temporary Weapon Repair code [DracoRPG] - pc_delitem(sd, pc_search_inventory(sd, 999), 1, 0); + pc_delitem(sd, pc_search_inventory(sd, material), 1, 0); clif_equiplist(sd); - clif_produceeffect(sd, 0, sd->status.inventory[idx].nameid); + clif_produceeffect(sd, 0, item->nameid); clif_misceffect(&sd->bl, 3); clif_displaymessage(sd->fd,"Item has been repaired."); } @@ -3486,63 +2720,49 @@ int pc_item_repair(struct map_session_data *sd,int idx) */ int pc_item_refine(struct map_session_data *sd,int idx) { - int flag = 1, i = 0, count = 0, ep = 0, per, refine; + int flag = 1, i = 0, ep = 0, per; int material[5] = { 0, 1010, 1011, 984, 984 }; - + struct item *item; + nullpo_retr(0, sd); - struct item *item = &sd->status.inventory[idx]; + item = &sd->status.inventory[idx]; if(idx >= 0 && idx < MAX_INVENTORY) { if(item->nameid > 0 && itemdb_type(item->nameid)==4) { // if it's no longer refineable - if (item->refine == 10) { + if (item->refine >= sd->skilllv || item->refine == 10) { clif_skill_fail(sd,sd->skillid,0,0); return 0; } - refine = item->refine + sd->skilllv > 10 - ? 10 - item->refine : sd->skilllv; - for (i=0; i < MAX_INVENTORY; i++) - if(sd->status.inventory[i].nameid == material [itemdb_wlv (item->nameid)]) - count += sd->status.inventory[i].amount; - if (count < refine ) { + if ((i=pc_search_inventory(sd, material [itemdb_wlv (item->nameid)])) < 0 ) { //fixed by Lupus (item pos can be = 0!) clif_skill_fail(sd,sd->skillid,0,0); return 0; } - per = percentrefinery [itemdb_wlv (item->nameid)][item->refine + refine - 1]; + + per = percentrefinery [itemdb_wlv (item->nameid)][(int)item->refine]; //per += pc_checkskill(sd,BS_WEAPONRESEARCH); per *= (75 + sd->status.job_level/2)/100; - + if (per > rand() % 100) { flag = 0; - item->refine += refine; - - for (i=0; i < MAX_INVENTORY; i++) - if(sd->status.inventory[i].nameid == material [itemdb_wlv (item->nameid)]) { - if (sd->status.inventory[i].amount >= refine) { - pc_delitem(sd,i,refine,0); - break; - } else { - refine -= sd->status.inventory[i].amount; - pc_delitem(sd,i,sd->status.inventory[i].amount,0); - } - } - + item->refine++; + pc_delitem(sd, i, 1, 0); if(item->equip) { ep = item->equip; - pc_unequipitem(sd,idx,0, BF_NORMAL); + pc_unequipitem(sd,idx,3); } clif_refine(sd->fd,sd,0,idx,item->refine); - clif_delitem(sd,idx,1); + clif_delitem(sd,idx,1); clif_additem(sd,idx,1,0); if (ep) pc_equipitem(sd,idx,ep); clif_misceffect(&sd->bl,3); } else { - clif_delitem(sd,i,refine); + pc_delitem(sd, i, 1, 0); item->refine = 0; if(item->equip) - pc_unequipitem(sd,idx,0, BF_NORMAL); + pc_unequipitem(sd,idx,3); clif_refine(sd->fd,sd,1,idx,item->refine); pc_delitem(sd,idx,1,0); clif_misceffect(&sd->bl,2); @@ -3596,28 +2816,29 @@ int pc_show_steal(struct block_list *bl,va_list ap) int pc_steal_item(struct map_session_data *sd,struct block_list *bl) { if(sd != NULL && bl != NULL && bl->type == BL_MOB) { - int i,skill,rate,itemid,flag, count; + int i,skill,itemid,flag, count; struct mob_data *md; md=(struct mob_data *)bl; - if(!md->state.steal_flag && mob_db[md->class].mexp <= 0 && !(mob_db[md->class].mode&0x20) && md->sc_data[SC_STONE].timer == -1 && md->sc_data[SC_FREEZE].timer == -1 && - (!(md->class>1324 && md->class<1364))) // prevent stealing from treasure boxes [Valaris] + if(!md->state.steal_flag && mob_db[md->class_].mexp <= 0 && !(mob_db[md->class_].mode&0x20) && + (!(md->class_>1324 && md->class_<1364))) // prevent stealing from treasure boxes [Valaris] { + if (md->sc_data && (md->sc_data[SC_STONE].timer != -1 || md->sc_data[SC_FREEZE].timer != -1)) + return 0; skill = battle_config.skill_steal_type == 1 - ? (sd->paramc[4] - mob_db[md->class].dex)/2 + pc_checkskill(sd,TF_STEAL)*6 + 10 - : sd->paramc[4] - mob_db[md->class].dex + pc_checkskill(sd,TF_STEAL)*3 + 10; + ? (sd->paramc[4] - mob_db[md->class_].dex)/2 + pc_checkskill(sd,TF_STEAL)*6 + 10 + : sd->paramc[4] - mob_db[md->class_].dex + pc_checkskill(sd,TF_STEAL)*3 + 10; if(0 < skill) { - for(count = 8; count <= 8 && count != 0; count--) + for(count = 10; count <= 10 && count != 0; count--) //8 -> 10 Lupus { - i = rand()%8; - itemid = mob_db[md->class].dropitem[i].nameid; + i = rand()%10; //8 -> 10 Lupus + itemid = mob_db[md->class_].dropitem[i].nameid; if(itemid > 0 && itemdb_type(itemid) != 6) { - rate = (mob_db[md->class].dropitem[i].p / battle_config.item_rate_common * 100 * skill)/100; - - if(rand()%10000 < rate) + //fixed rate. From Freya [Lupus] + if (rand() % 10000 < ((mob_db[md->class_].dropitem[i].p * skill) / 100 + sd->add_steal_rate)) { struct item tmp_item; memset(&tmp_item,0,sizeof(tmp_item)); @@ -3659,11 +2880,13 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *bl) if(sd != NULL && bl != NULL && bl->type == BL_MOB) { int rate,skill; struct mob_data *md=(struct mob_data *)bl; - if(md && !md->state.steal_coin_flag && md->sc_data && md->sc_data[SC_STONE].timer == -1 && md->sc_data[SC_FREEZE].timer == -1) { + if(md && !md->state.steal_coin_flag) { + if (md->sc_data && (md->sc_data[SC_STONE].timer != -1 || md->sc_data[SC_FREEZE].timer != -1)) + return 0; skill = pc_checkskill(sd,RG_STEALCOIN)*10; - rate = skill + (sd->status.base_level - mob_db[md->class].lv)*3 + sd->paramc[4]*2 + sd->paramc[5]*2; + rate = skill + (sd->status.base_level - mob_db[md->class_].lv)*3 + sd->paramc[4]*2 + sd->paramc[5]*2; if(rand()%1000 < rate) { - pc_getzeny(sd,mob_db[md->class].lv*10 + rand()%100); + pc_getzeny(sd,mob_db[md->class_].lv*10 + rand()%100); md->state.steal_coin_flag = 1; return 1; } @@ -3682,7 +2905,7 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *bl) int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrtype) { char mapname[24]; - int m=0,c=0,disguise=0; + int m=0,disguise=0; nullpo_retr(0, sd); @@ -3711,43 +2934,58 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt skill_gangsterparadise(sd,0); } - if(sd->sc_data[SC_TRICKDEAD].timer != -1) - skill_status_change_end(&sd->bl, SC_TRICKDEAD, -1); + if (sd->sc_count) { + if(sd->sc_data[SC_TRICKDEAD].timer != -1) + status_change_end(&sd->bl, SC_TRICKDEAD, -1); + if(sd->sc_data[SC_BLADESTOP].timer!=-1) + status_change_end(&sd->bl,SC_BLADESTOP,-1); + if(sd->sc_data[SC_DANCING].timer!=-1) // clear dance effect when warping [Valaris] + skill_stop_dancing(&sd->bl,0); + if (sd->sc_data[SC_BASILICA].timer!=-1) { + /*int i; + for (i=0;i<MAX_SKILLUNITGROUP;i++) + if (sd->skillunit[i].skill_id==HP_BASILICA) + skill_delunitgroup(&sd->skillunit[i]);*/ + + struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc_data[SC_BASILICA].val4; + if (sg && sg->src_id == sd->bl.id) + skill_delunitgroup (sg); + status_change_end(&sd->bl,SC_BASILICA,-1); + } + } + if(sd->status.option&2) - skill_status_change_end(&sd->bl, SC_HIDING, -1); + status_change_end(&sd->bl, SC_HIDING, -1); if(sd->status.option&4) - skill_status_change_end(&sd->bl, SC_CLOAKING, -1); - if(sd->status.option&16386) - skill_status_change_end(&sd->bl, SC_CHASEWALK, -1); - if(sd->sc_data[SC_BLADESTOP].timer!=-1) - skill_status_change_end(&sd->bl,SC_BLADESTOP,-1); - if(sd->sc_data[SC_DANCING].timer!=-1) // clear dance effect when warping [Valaris] - skill_stop_dancing(&sd->bl,0); + status_change_end(&sd->bl, SC_CLOAKING, -1); + if(sd->status.option&16384) + status_change_end(&sd->bl, SC_CHASEWALK, -1); if(sd->status.pet_id > 0 && sd->pd && sd->pet.intimate > 0) { pet_stopattack(sd->pd); pet_changestate(sd->pd,MS_IDLE,0); } - + if(sd->disguise) { // clear disguises when warping [Valaris] clif_clearchar(&sd->bl, 9); disguise=sd->disguise; sd->disguise=0; } - memcpy(mapname,mapname_org,24); + strncpy(mapname,mapname_org,sizeof(mapname)); mapname[16]=0; - if(strstr(mapname,".gat")==NULL && strlen(mapname)<16){ + if(strstr(mapname,".gat")==NULL && strstr(mapname,".afm")==NULL && strlen(mapname)<16){ strcat(mapname,".gat"); } m=map_mapname2mapid(mapname); + if(m<0){ if(sd->mapname[0]){ int ip,port; if(map_mapname2ipport(mapname,&ip,&port)==0){ skill_stop_dancing(&sd->bl,1); - skill_unit_out_all(&sd->bl,gettick(),1); + skill_unit_move(&sd->bl,gettick(),0); clif_clearchar_area(&sd->bl,clrtype&0xffff); skill_gangsterparadise(sd,0); map_delblock(&sd->bl); @@ -3759,7 +2997,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt sd->pd = NULL; sd->petDB = NULL; if(battle_config.pet_status_support) - pc_calcstatus(sd,2); + status_calc_pc(sd,2); } else if(sd->pet.intimate > 0) { pet_stopattack(sd->pd); @@ -3772,11 +3010,13 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt sd->bl.x=x; sd->bl.y=y; sd->state.waitingdisconnect=1; + pc_clean_skilltree(sd); pc_makesavestatus(sd); if(sd->status.pet_id > 0 && sd->pd) intif_save_petdata(sd->status.account_id,&sd->pet); chrif_save(sd); storage_storage_save(sd); + storage_delete(sd->status.account_id); chrif_changemapserver(sd, mapname, x, y, ip, port); return 0; } @@ -3790,7 +3030,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt if(x <0 || x >= map[m].xs || y <0 || y >= map[m].ys) x=y=0; - if((x==0 && y==0) || (c=read_gat(m,x,y))==1 || c==5){ + if((x==0 && y==0) || map_getcell(m,x,y,CELL_CHKNOPASS)){ if(x||y) { if(battle_config.error_log) printf("stacked (%d,%d)\n",x,y); @@ -3798,11 +3038,11 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt do { x=rand()%(map[m].xs-2)+1; y=rand()%(map[m].ys-2)+1; - } while((c=read_gat(m,x,y))==1 || c==5); + } while(map_getcell(m,x,y,CELL_CHKNOPASS)); } if(sd->mapname[0] && sd->bl.prev != NULL){ - skill_unit_out_all(&sd->bl,gettick(),1); + skill_unit_move(&sd->bl,gettick(),0); clif_clearchar_area(&sd->bl,clrtype&0xffff); skill_gangsterparadise(sd,0); map_delblock(&sd->bl); @@ -3815,7 +3055,8 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt sd->pd = NULL; sd->petDB = NULL; if(battle_config.pet_status_support) - pc_calcstatus(sd,2); + status_calc_pc(sd,2); + pc_clean_skilltree(sd); pc_makesavestatus(sd); chrif_save(sd); storage_storage_save(sd); @@ -3832,13 +3073,13 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt if(disguise) // disguise teleport fix [Valaris] sd->disguise=disguise; - + memcpy(sd->mapname,mapname,24); sd->bl.m = m; sd->to_x = x; sd->to_y = y; - // moved and changed dance effect stopping + // moved and changed dance effect stopping sd->bl.x = x; sd->bl.y = y; @@ -3861,7 +3102,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt *------------------------------------------ */ int pc_randomwarp(struct map_session_data *sd, int type) { - int x,y,c,i=0; + int x,y,i=0; int m; nullpo_retr(0, sd); @@ -3874,7 +3115,7 @@ int pc_randomwarp(struct map_session_data *sd, int type) { do{ x=rand()%(map[m].xs-2)+1; y=rand()%(map[m].ys-2)+1; - } while (((c=read_gat(m,x,y)) == 1 || c == 5) && (i++) < 1000); + }while(map_getcell(m,x,y,CELL_CHKNOPASS) && (i++)<1000 ); if (i < 1000) pc_setpos(sd,map[m].name,x,y,type); @@ -3957,7 +3198,7 @@ int pc_can_reach(struct map_session_data *sd,int x,int y) // ? s•¨ // /*========================================== - * ŽŸ‚Ì1?‚É‚©‚©‚鎞ŠÔ‚ðŒvŽZ + * ŽŸ‚Ì1?‚É‚©‚©‚éŽjÔ‚ðŒvŽZ *------------------------------------------ */ static int calc_next_walk_step(struct map_session_data *sd) @@ -3979,12 +3220,11 @@ static int calc_next_walk_step(struct map_session_data *sd) static int pc_walk(int tid,unsigned int tick,int id,int data) { struct map_session_data *sd; - int i,ctype; + int i; int moveblock; int x,y,dx,dy; - sd=map_id2sd(id); - if(sd==NULL) + if ((sd = map_id2sd(id)) == NULL) return 0; if(sd->walktimer != tid){ @@ -4001,32 +3241,34 @@ static int pc_walk(int tid,unsigned int tick,int id,int data) sd->inchealspiritsptick = 0; sd->walkpath.path_half ^= 1; - if(sd->walkpath.path_half==0){ // ƒ}ƒX–Ú’†S‚Ö“ž’… + if(sd->walkpath.path_half==0){ // ƒ}ƒX–Ú’†S‚Ö“r sd->walkpath.path_pos++; + if(sd->state.change_walk_target){ pc_walktoxy_sub(sd); return 0; } - } else { // ƒ}ƒX–Ú‹«ŠE‚Ö“ž’… + } else { // ƒ}ƒX–Ú‹«ŠE‚Ö“r if(sd->walkpath.path[sd->walkpath.path_pos]>=8) return 1; x = sd->bl.x; y = sd->bl.y; - ctype = map_getcell(sd->bl.m,x,y); - if(ctype == 1 || ctype == 5) { + if(map_getcell(sd->bl.m,x,y,CELL_CHKNOPASS)) { pc_stop_walking(sd,1); return 0; } sd->dir=sd->head_dir=sd->walkpath.path[sd->walkpath.path_pos]; dx = dirx[(int)sd->dir]; dy = diry[(int)sd->dir]; - ctype = map_getcell(sd->bl.m,x+dx,y+dy); - if(ctype == 1 || ctype == 5) { + if(map_getcell(sd->bl.m,x,y,CELL_CHKNOPASS)) { pc_walktoxy_sub(sd); return 0; } - + if (skill_check_moonlit (&sd->bl,x+dx,y+dy)) { + pc_stop_walking(sd,1); + return 0; + } moveblock = ( x/BLOCK_SIZE != (x+dx)/BLOCK_SIZE || y/BLOCK_SIZE != (y+dy)/BLOCK_SIZE); sd->walktimer = 1; @@ -4035,26 +3277,12 @@ static int pc_walk(int tid,unsigned int tick,int id,int data) x += dx; y += dy; + skill_unit_move(&sd->bl,tick,0); if(moveblock) map_delblock(&sd->bl); sd->bl.x = x; sd->bl.y = y; if(moveblock) map_addblock(&sd->bl); - - if (sd->status.guild_id > 0) { - struct skill_unit *su; - if (sd->sc_data[SC_LEADERSHIP].val4 && (su=(struct skill_unit *)sd->sc_data[SC_LEADERSHIP].val4)) { - skill_unit_move_unit_group(su->group,sd->bl.m,dx,dy); - } - if (sd->sc_data[SC_GLORYWOUNDS].val4 && (su=(struct skill_unit *)sd->sc_data[SC_GLORYWOUNDS].val4)) { - skill_unit_move_unit_group(su->group,sd->bl.m,dx,dy); - } - if (sd->sc_data[SC_SOULCOLD].val4 && (su=(struct skill_unit *)sd->sc_data[SC_SOULCOLD].val4)) { - skill_unit_move_unit_group(su->group,sd->bl.m,dx,dy); - } - if (sd->sc_data[SC_HAWKEYES].val4 && (su=(struct skill_unit *)sd->sc_data[SC_HAWKEYES].val4)) { - skill_unit_move_unit_group(su->group,sd->bl.m,dx,dy); - } - } + skill_unit_move(&sd->bl,tick,1); map_foreachinmovearea(clif_pcinsight,sd->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,-dx,-dy,0,sd); sd->walktimer = -1; @@ -4084,21 +3312,18 @@ static int pc_walk(int tid,unsigned int tick,int id,int data) if (sd->sc_data[SC_DEVOTION].val1) skill_devotion2(&sd->bl,sd->sc_data[SC_DEVOTION].val1); - if (sd->sc_data[SC_BASILICA].timer != -1) { // Basilica cancels if caster moves [celest] - struct skill_unit *su; - if ((su = (struct skill_unit *)sd->sc_data[SC_BASILICA].val4)) { - struct skill_unit_group *sg; - if ((sg = su->group) && sg->src_id == sd->bl.id) { - skill_status_change_end(&sd->bl,SC_BASILICA,-1); - skill_delunitgroup (sg); - } - } + if (sd->sc_data[SC_BASILICA].timer!=-1) { // Basilica cancels if caster moves [celest] + /*int i; + for (i=0;i<MAX_SKILLUNITGROUP;i++) + if (sd->skillunit[i].skill_id==HP_BASILICA*/ + struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc_data[SC_BASILICA].val4; + if (sg && sg->src_id == sd->bl.id) + skill_delunitgroup (sg); + status_change_end(&sd->bl,SC_BASILICA,-1); } } - skill_unit_move(&sd->bl,tick,1); // ƒXƒLƒ‹ƒ†ƒjƒbƒg‚Ì?¸ - - if(map_getcell(sd->bl.m,x,y)&0x80) + if(map_getcell(sd->bl.m,x,y,CELL_CHKNPC)) npc_touch_areanpc(sd,sd->bl.m,x,y); else sd->areanpc_id=0; @@ -4109,6 +3334,8 @@ static int pc_walk(int tid,unsigned int tick,int id,int data) i = 1; sd->walktimer=add_timer(tick+i,pc_walk,id,sd->walkpath.path_pos); } + if(battle_config.disp_hpmeter) + clif_hpmeter(sd); return 0; } @@ -4151,15 +3378,24 @@ int pc_walktoxy(struct map_session_data *sd,int x,int y) sd->to_x=x; sd->to_y=y; + sd->idletime = tick_; if(sd->walktimer != -1 && sd->state.change_walk_target==0){ - // Œ»Ý?‚¢‚Ä‚¢‚éÅ’†‚Ì–Ú“I’n?X‚Ȃ̂Ń}ƒX–Ú‚Ì’†S‚É?‚½Žž‚É + // Œ»Ý?‚¢‚Ä‚¢‚éÅ’†‚Ì–Ú“I’n?X‚Ȃ̂Ń}ƒX–Ú‚Ì’†S‚É?‚½ŽbÉ // timer??‚©‚çpc_walktoxy_sub‚ðŒÄ‚Ԃ悤‚É‚·‚é sd->state.change_walk_target=1; } else { pc_walktoxy_sub(sd); } + if (sd->state.gmaster_flag > 0) { + struct guild *g = (struct guild *)sd->state.gmaster_flag; + if (g) + map_foreachinarea (skill_guildaura_sub, sd->bl.m, + sd->bl.x-2, sd->bl.y-2, sd->bl.x+2, sd->bl.y+2, BL_PC, + sd->bl.id, sd->status.guild_id, g); + } + return 0; } @@ -4182,7 +3418,7 @@ int pc_stop_walking(struct map_session_data *sd,int type) clif_fixpos(&sd->bl); if(type&0x02 && battle_config.pc_damage_delay) { unsigned int tick = gettick(); - int delay = battle_get_dmotion(&sd->bl); + int delay = status_get_dmotion(&sd->bl); if(sd->canmove_tick < tick) sd->canmove_tick = tick + delay; } @@ -4191,13 +3427,47 @@ int pc_stop_walking(struct map_session_data *sd,int type) } /*========================================== + * Random walk + *------------------------------------------ + */ +int pc_randomwalk(struct map_session_data *sd,int tick) +{ + const int retrycount = 20; + nullpo_retr(0, sd); + + if(DIFF_TICK(sd->next_walktime,tick)<0){ + int i,x,y,d; + d = rand()%7+5; + for(i=0;i<retrycount;i++){ // Search of a movable place + int r=rand(); + x=sd->bl.x+r%(d*2+1)-d; + y=sd->bl.y+r/(d*2+1)%(d*2+1)-d; + if((map_getcell(sd->bl.m,x,y,CELL_CHKPASS)) && pc_walktoxy(sd,x,y)==0) + break; + } + // Working on this part later [celest] + /*for(i=c=0;i<sd->walkpath.path_len;i++){ // The next walk start time is calculated. + if(sd->walkpath.path[i]&1) + c+=sd->speed*14/10; + else + c+=sd->speed; + } + sd->next_walktime = (d=tick+rand()%3000+c); + return d;*/ + return 1; + } + return 0; +} + +/*========================================== * *------------------------------------------ */ int pc_movepos(struct map_session_data *sd,int dst_x,int dst_y) { int moveblock; - int dx,dy,dist; + int dx,dy; + int tick = gettick(); struct walkpath_data wpd; @@ -4210,16 +3480,17 @@ int pc_movepos(struct map_session_data *sd,int dst_x,int dst_y) dx = dst_x - sd->bl.x; dy = dst_y - sd->bl.y; - dist = distance(sd->bl.x,sd->bl.y,dst_x,dst_y); moveblock = ( sd->bl.x/BLOCK_SIZE != dst_x/BLOCK_SIZE || sd->bl.y/BLOCK_SIZE != dst_y/BLOCK_SIZE); map_foreachinmovearea(clif_pcoutsight,sd->bl.m,sd->bl.x-AREA_SIZE,sd->bl.y-AREA_SIZE,sd->bl.x+AREA_SIZE,sd->bl.y+AREA_SIZE,dx,dy,0,sd); + skill_unit_move(&sd->bl,tick,0); if(moveblock) map_delblock(&sd->bl); sd->bl.x = dst_x; sd->bl.y = dst_y; if(moveblock) map_addblock(&sd->bl); + skill_unit_move(&sd->bl,tick,1); map_foreachinmovearea(clif_pcinsight,sd->bl.m,sd->bl.x-AREA_SIZE,sd->bl.y-AREA_SIZE,sd->bl.x+AREA_SIZE,sd->bl.y+AREA_SIZE,-dx,-dy,0,sd); @@ -4236,9 +3507,7 @@ int pc_movepos(struct map_session_data *sd,int dst_x,int dst_y) if(sd->status.option&4) // ƒNƒ?ƒLƒ“ƒO‚ÌÁ–Å?¸ skill_check_cloaking(&sd->bl); - skill_unit_move(&sd->bl,gettick(),dist+7); // ƒXƒLƒ‹ƒ†ƒjƒbƒg‚Ì?¸ - - if(map_getcell(sd->bl.m,sd->bl.x,sd->bl.y)&0x80) + if(map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNPC)) npc_touch_areanpc(sd,sd->bl.m,sd->bl.x,sd->bl.y); else sd->areanpc_id=0; @@ -4281,46 +3550,44 @@ int pc_checkskill(struct map_session_data *sd,int skill_id) int pc_checkallowskill(struct map_session_data *sd) { nullpo_retr(0, sd); - - if( sd->sc_data == NULL ) - return 0; + nullpo_retr(0, sd->sc_data); if(!(skill_get_weapontype(KN_TWOHANDQUICKEN)&(1<<sd->status.weapon)) && sd->sc_data[SC_TWOHANDQUICKEN].timer!=-1) { // 2HQ - skill_status_change_end(&sd->bl,SC_TWOHANDQUICKEN,-1); // 2HQ‚ð‰ðœ + status_change_end(&sd->bl,SC_TWOHANDQUICKEN,-1); // 2HQ‚ð‰ðœ return -1; } if(!(skill_get_weapontype(LK_AURABLADE)&(1<<sd->status.weapon)) && sd->sc_data[SC_AURABLADE].timer!=-1) { /* ƒI?ƒ‰ƒuƒŒ?ƒh */ - skill_status_change_end(&sd->bl,SC_AURABLADE,-1); /* ƒI?ƒ‰ƒuƒŒ?ƒh‚ð‰ðœ */ + status_change_end(&sd->bl,SC_AURABLADE,-1); /* ƒI?ƒ‰ƒuƒŒ?ƒh‚ð‰ðœ */ return -1; } if(!(skill_get_weapontype(LK_PARRYING)&(1<<sd->status.weapon)) && sd->sc_data[SC_PARRYING].timer!=-1) { /* ƒpƒŠƒCƒ“ƒO */ - skill_status_change_end(&sd->bl,SC_PARRYING,-1); /* ƒpƒŠƒCƒ“ƒO‚ð‰ðœ */ + status_change_end(&sd->bl,SC_PARRYING,-1); /* ƒpƒŠƒCƒ“ƒO‚ð‰ðœ */ return -1; } if(!(skill_get_weapontype(LK_CONCENTRATION)&(1<<sd->status.weapon)) && sd->sc_data[SC_CONCENTRATION].timer!=-1) { /* ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ */ - skill_status_change_end(&sd->bl,SC_CONCENTRATION,-1); /* ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“‚ð‰ðœ */ + status_change_end(&sd->bl,SC_CONCENTRATION,-1); /* ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“‚ð‰ðœ */ return -1; } if(!(skill_get_weapontype(CR_SPEARQUICKEN)&(1<<sd->status.weapon)) && sd->sc_data[SC_SPEARSQUICKEN].timer!=-1){ // ƒXƒsƒAƒNƒBƒbƒPƒ“ - skill_status_change_end(&sd->bl,SC_SPEARSQUICKEN,-1); // ƒXƒsƒAƒNƒCƒbƒPƒ“‚ð‰ðœ + status_change_end(&sd->bl,SC_SPEARSQUICKEN,-1); // ƒXƒsƒAƒNƒCƒbƒPƒ“‚ð‰ðœ return -1; } if(!(skill_get_weapontype(BS_ADRENALINE)&(1<<sd->status.weapon)) && sd->sc_data[SC_ADRENALINE].timer!=-1){ // ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… - skill_status_change_end(&sd->bl,SC_ADRENALINE,-1); // ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ…‚ð‰ðœ + status_change_end(&sd->bl,SC_ADRENALINE,-1); // ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ…‚ð‰ðœ return -1; } if(sd->status.shield <= 0) { if(sd->sc_data[SC_AUTOGUARD].timer!=-1){ // ƒI?ƒgƒK?ƒh - skill_status_change_end(&sd->bl,SC_AUTOGUARD,-1); + status_change_end(&sd->bl,SC_AUTOGUARD,-1); return -1; } if(sd->sc_data[SC_DEFENDER].timer!=-1){ // ƒfƒBƒtƒFƒ“ƒ_? - skill_status_change_end(&sd->bl,SC_DEFENDER,-1); + status_change_end(&sd->bl,SC_DEFENDER,-1); return -1; } if(sd->sc_data[SC_REFLECTSHIELD].timer!=-1){ //ƒŠƒtƒŒƒNƒgƒV?ƒ‹ƒh - skill_status_change_end(&sd->bl,SC_REFLECTSHIELD,-1); + status_change_end(&sd->bl,SC_REFLECTSHIELD,-1); return -1; } } @@ -4372,10 +3639,6 @@ struct pc_base_job pc_calc_base_job(int b_class) bj.upper = 2; } - if(battle_config.enable_upper_class==0){ //conf‚Å–³?‚ɂȂÁ‚Ä‚¢‚½‚çupper=0 - bj.upper = 0; - } - if(bj.job == 0){ bj.type = 0; }else if(bj.job < 7){ @@ -4383,7 +3646,7 @@ struct pc_base_job pc_calc_base_job(int b_class) }else{ bj.type = 2; } - + return bj; } @@ -4399,7 +3662,7 @@ int pc_calc_base_job2 (int b_class) return b_class - 4001; else if(b_class == 4045) return 23; - return b_class - 4023; + return b_class - 4023; } int pc_calc_upper(int b_class) @@ -4426,6 +3689,9 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data) sd=map_id2sd(id); if(sd == NULL) return 0; + + sd->idletime = tick_; + if(sd->attacktimer != tid){ if(battle_config.error_log) printf("pc_attack_timer %d != %d\n",sd->attacktimer,tid); @@ -4440,8 +3706,12 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data) if(bl==NULL || bl->prev == NULL) return 0; - if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) - return 0; + if(bl->type == BL_PC) { + if (pc_isdead((struct map_session_data *)bl)) + return 0; + else if (pc_ishiding((struct map_session_data *)bl)) + return 0; + } // “¯‚¶map‚łȂ¢‚È‚çU?‚µ‚È‚¢ // PC‚ªŽ€‚ñ‚łĂàU?‚µ‚È‚¢ @@ -4452,17 +3722,21 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data) if( sd->opt1>0 || sd->status.option&2 || sd->status.option&16384) // ˆÙí‚ȂǂÅU?‚Å‚«‚È‚¢ return 0; - if(sd->sc_data[SC_AUTOCOUNTER].timer != -1) - return 0; - if(sd->sc_data[SC_BLADESTOP].timer != -1) - return 0; + if (sd->sc_count) { + if(sd->sc_data[SC_AUTOCOUNTER].timer != -1) + return 0; + if(sd->sc_data[SC_BLADESTOP].timer != -1) + return 0; + } - //if((opt = battle_get_option(bl)) != NULL && *opt&0x46) - if((opt = battle_get_option(bl)) != NULL && *opt&0x42) + //if((opt = status_get_option(bl)) != NULL && *opt&0x46) + if((opt = status_get_option(bl)) != NULL && *opt&0x42) return 0; - if(((sc_data = battle_get_sc_data(bl)) != NULL && sc_data[SC_TRICKDEAD].timer != -1) || - ((sc_data = battle_get_sc_data(bl)) != NULL && sc_data[SC_BASILICA].timer != -1 )) + if((sc_data = status_get_sc_data(bl)) != NULL) { + if (sc_data[SC_TRICKDEAD].timer != -1 || + sc_data[SC_BASILICA].timer != -1) return 0; + } if(sd->skilltimer != -1 && pc_checkskill(sd,SA_FREECAST) <= 0) return 0; @@ -4474,6 +3748,11 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data) } } + if(sd->status.weapon == 11 && sd->equip_index[10] < 0) { + clif_arrow_fail(sd,0); + return 0; + } + dist = distance(sd->bl.x,sd->bl.y,bl->x,bl->y); range = sd->attackrange; if(sd->status.weapon != 11) range++; @@ -4501,7 +3780,7 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data) sd->attacktarget_lv = battle_weapon_attack(&sd->bl,bl,tick,0); // &2 = ? - Celest if(!(battle_config.pc_cloak_check_type&2) && sd->sc_data[SC_CLOAKING].timer != -1) - skill_status_change_end(&sd->bl,SC_CLOAKING,-1); + status_change_end(&sd->bl,SC_CLOAKING,-1); if(sd->status.pet_id > 0 && sd->pd && sd->petDB && battle_config.pet_attack_support) pet_target_check(sd,bl,0); map_freeblock_unlock(); @@ -4536,19 +3815,22 @@ int pc_attack(struct map_session_data *sd,int target_id,int type) struct block_list *bl; int d; + nullpo_retr(0, sd); bl=map_id2bl(target_id); if(bl==NULL) return 1; - + + sd->idletime = tick_; + if(bl->type==BL_NPC) { // monster npcs [Valaris] //npc_click(sd,RFIFOL(sd->fd,2)); npc_click(sd,target_id); // submitted by leinsirk10 [Celest] return 0; } - - if(!battle_check_target(&sd->bl,bl,BCT_ENEMY)) + + if(battle_check_target(&sd->bl,bl,BCT_ENEMY) <= 0) return 1; if(sd->attacktimer != -1) pc_stopattack(sd); @@ -4589,7 +3871,8 @@ int pc_follow_timer(int tid,unsigned int tick,int id,int data) struct map_session_data *sd, *bl; sd=map_id2sd(id); - if(sd == NULL || sd->followtimer != tid) + + if(sd == NULL || sd->followtimer != tid || pc_isdead(sd)) return 0; sd->followtimer=-1; @@ -4648,7 +3931,7 @@ int pc_checkbaselevelup(struct map_session_data *sd) nullpo_retr(0, sd); if(sd->status.base_exp >= next && next > 0){ - struct pc_base_job s_class = pc_calc_base_job(sd->status.class); + struct pc_base_job s_class = pc_calc_base_job(sd->status.class_); // base‘¤ƒŒƒxƒ‹ƒAƒbƒv?— sd->status.base_exp -= next; @@ -4658,16 +3941,16 @@ int pc_checkbaselevelup(struct map_session_data *sd) clif_updatestatus(sd,SP_STATUSPOINT); clif_updatestatus(sd,SP_BASELEVEL); clif_updatestatus(sd,SP_NEXTBASEEXP); - pc_calcstatus(sd,0); + status_calc_pc(sd,0); pc_heal(sd,sd->status.max_hp,sd->status.max_sp); //ƒXƒpƒmƒr‚̓LƒŠƒGAƒCƒ€ƒ|Aƒ}ƒjƒsAƒOƒAƒTƒtƒ‰Lv1‚ª‚©‚©‚é if(s_class.job == 23){ - skill_status_change_start(&sd->bl,SkillStatusChangeTable[PR_KYRIE],1,0,0,0,skill_get_time(PR_KYRIE,1),0 ); - skill_status_change_start(&sd->bl,SkillStatusChangeTable[PR_IMPOSITIO],1,0,0,0,skill_get_time(PR_IMPOSITIO,1),0 ); - skill_status_change_start(&sd->bl,SkillStatusChangeTable[PR_MAGNIFICAT],1,0,0,0,skill_get_time(PR_MAGNIFICAT,1),0 ); - skill_status_change_start(&sd->bl,SkillStatusChangeTable[PR_GLORIA],1,0,0,0,skill_get_time(PR_GLORIA,1),0 ); - skill_status_change_start(&sd->bl,SkillStatusChangeTable[PR_SUFFRAGIUM],1,0,0,0,skill_get_time(PR_SUFFRAGIUM,1),0 ); + status_change_start(&sd->bl,SkillStatusChangeTable[PR_KYRIE],1,0,0,0,skill_get_time(PR_KYRIE,1),0 ); + status_change_start(&sd->bl,SkillStatusChangeTable[PR_IMPOSITIO],1,0,0,0,skill_get_time(PR_IMPOSITIO,1),0 ); + status_change_start(&sd->bl,SkillStatusChangeTable[PR_MAGNIFICAT],1,0,0,0,skill_get_time(PR_MAGNIFICAT,1),0 ); + status_change_start(&sd->bl,SkillStatusChangeTable[PR_GLORIA],1,0,0,0,skill_get_time(PR_GLORIA,1),0 ); + status_change_start(&sd->bl,SkillStatusChangeTable[PR_SUFFRAGIUM],1,0,0,0,skill_get_time(PR_SUFFRAGIUM,1),0 ); } clif_misceffect(&sd->bl,0); @@ -4694,7 +3977,7 @@ int pc_checkjoblevelup(struct map_session_data *sd) clif_updatestatus(sd,SP_NEXTJOBEXP); sd->status.skill_point ++; clif_updatestatus(sd,SP_SKILLPOINT); - pc_calcstatus(sd,0); + status_calc_pc(sd,0); clif_misceffect(&sd->bl,1); return 1; @@ -4710,6 +3993,8 @@ int pc_checkjoblevelup(struct map_session_data *sd) int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp) { char output[256]; + float nextbp=0, nextjp=0; + int nextb=0, nextj=0; nullpo_retr(0, sd); if(sd->bl.prev == NULL || pc_isdead(sd)) @@ -4734,11 +4019,17 @@ int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp) if (base_exp < 0) base_exp = 0; } + nextb = pc_nextbaseexp(sd); + nextj = pc_nextjobexp(sd); + if (nextb > 0) + nextbp = (float) base_exp / (float) nextb; + if (nextj > 0) + nextjp = (float) job_exp / (float) nextj; sd->status.base_exp += base_exp; if(sd->status.base_exp < 0) sd->status.base_exp = 0; - + while(pc_checkbaselevelup(sd)) ; clif_updatestatus(sd,SP_BASEEXP); @@ -4751,14 +4042,14 @@ int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp) sd->status.job_exp += job_exp; if(sd->status.job_exp < 0) sd->status.job_exp = 0; - + while(pc_checkjoblevelup(sd)) ; clif_updatestatus(sd,SP_JOBEXP); - if(battle_config.disp_experience){ - sprintf(output, - "Experienced Gained Base:%d Job:%d",base_exp,job_exp); + if(battle_config.disp_experience && !sd->noexp){ + sprintf(output, + "Experienced Gained Base:%d (%.2f%%) Job:%d (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100); clif_disp_onlyself(sd,output,strlen(output)); } @@ -4778,12 +4069,12 @@ int pc_nextbaseexp(struct map_session_data *sd) if(sd->status.base_level>=MAX_LEVEL || sd->status.base_level<=0) return 0; - if(sd->status.class==0) i=0; - else if(sd->status.class<=6) i=1; - else if(sd->status.class<=22) i=2; - else if(sd->status.class==23) i=3; - else if(sd->status.class==4001) i=4; - else if(sd->status.class<=4007) i=5; + if(sd->status.class_==0) i=0; + else if(sd->status.class_<=6) i=1; + else if(sd->status.class_<=22) i=2; + else if(sd->status.class_==23) i=3; + else if(sd->status.class_==4001) i=4; + else if(sd->status.class_<=4007) i=5; else i=6; return exp_table[i][sd->status.base_level-1]; @@ -4802,12 +4093,12 @@ int pc_nextjobexp(struct map_session_data *sd) if(sd->status.job_level>=MAX_LEVEL || sd->status.job_level<=0) return 0; - if(sd->status.class==0) i=7; - else if(sd->status.class<=6) i=8; - else if(sd->status.class<=22) i=9; - else if(sd->status.class==23) i=10; - else if(sd->status.class==4001) i=11; - else if(sd->status.class<=4007) i=12; + if(sd->status.class_==0) i=7; + else if(sd->status.class_<=6) i=8; + else if(sd->status.class_<=22) i=9; + else if(sd->status.class_==23) i=10; + else if(sd->status.class_==4001) i=11; + else if(sd->status.class_<=4007) i=12; else i=13; return exp_table[i][sd->status.job_level-1]; @@ -4826,12 +4117,12 @@ int pc_nextbaseafter(struct map_session_data *sd) if(sd->status.base_level>=MAX_LEVEL || sd->status.base_level<=0) return 0; - if(sd->status.class==0) i=0; - else if(sd->status.class<=6) i=1; - else if(sd->status.class<=22) i=2; - else if(sd->status.class==23) i=3; - else if(sd->status.class==4001) i=4; - else if(sd->status.class<=4007) i=5; + if(sd->status.class_==0) i=0; + else if(sd->status.class_<=6) i=1; + else if(sd->status.class_<=22) i=2; + else if(sd->status.class_==23) i=3; + else if(sd->status.class_==4001) i=4; + else if(sd->status.class_<=4007) i=5; else i=6; return exp_table[i][sd->status.base_level]; @@ -4850,12 +4141,12 @@ int pc_nextjobafter(struct map_session_data *sd) if(sd->status.job_level>=MAX_LEVEL || sd->status.job_level<=0) return 0; - if(sd->status.class==0) i=7; - else if(sd->status.class<=6) i=8; - else if(sd->status.class<=22) i=9; - else if(sd->status.class==23) i=10; - else if(sd->status.class==4001) i=11; - else if(sd->status.class<=4007) i=12; + if(sd->status.class_==0) i=7; + else if(sd->status.class_<=6) i=8; + else if(sd->status.class_<=22) i=9; + else if(sd->status.class_==23) i=10; + else if(sd->status.class_==4001) i=11; + else if(sd->status.class_<=4007) i=12; else i=13; return exp_table[i][sd->status.job_level]; @@ -4890,10 +4181,10 @@ int pc_need_status_point(struct map_session_data *sd,int type) int pc_statusup(struct map_session_data *sd,int type) { int max, need,val = 0; - + nullpo_retr(0, sd); - max = (pc_calc_upper(sd->status.class)==2) ? 80 : battle_config.max_parameter; + max = (pc_calc_upper(sd->status.class_)==2) ? 80 : battle_config.max_parameter; need=pc_need_status_point(sd,type); if(type<SP_STR || type>SP_LUK || need<0 || need>sd->status.status_point){ @@ -4950,7 +4241,7 @@ int pc_statusup(struct map_session_data *sd,int type) } clif_updatestatus(sd,SP_STATUSPOINT); clif_updatestatus(sd,type); - pc_calcstatus(sd,0); + status_calc_pc(sd,0); clif_statusupack(sd,type,1,val); return 0; @@ -5026,7 +4317,7 @@ int pc_statusup2(struct map_session_data *sd,int type,int val) } clif_updatestatus(sd,type-SP_STR+SP_USTR); clif_updatestatus(sd,type); - pc_calcstatus(sd,0); + status_calc_pc(sd,0); clif_statusupack(sd,type,1,val); return 0; @@ -5048,11 +4339,11 @@ int pc_skillup(struct map_session_data *sd,int skill_num) if( sd->status.skill_point>0 && sd->status.skill[skill_num].id!=0 && //sd->status.skill[skill_num].lv < skill_get_max(skill_num) ) - celest - sd->status.skill[skill_num].lv < skill_tree_get_max(skill_num, sd->status.class) ) + sd->status.skill[skill_num].lv < skill_tree_get_max(skill_num, sd->status.class_) ) { sd->status.skill[skill_num].lv++; sd->status.skill_point--; - pc_calcstatus(sd,0); + status_calc_pc(sd,0); clif_skillup(sd,skill_num); clif_updatestatus(sd,SP_SKILLPOINT); clif_skillinfoblock(sd); @@ -5074,7 +4365,7 @@ int pc_allskillup(struct map_session_data *sd) nullpo_retr(0, sd); - s_class = pc_calc_base_job(sd->status.class); + s_class = pc_calc_base_job(sd->status.class_); c = s_class.job; s = (s_class.upper==1) ? 1 : 0 ; //?¶ˆÈŠO‚Í’Êí‚̃XƒLƒ‹H @@ -5092,21 +4383,25 @@ int pc_allskillup(struct map_session_data *sd) sd->status.skill[i].lv=skill_get_max(i); for(i=210;i<291;i++) sd->status.skill[i].lv=skill_get_max(i); - for(i=304;i<MAX_SKILL;i++){ + for(i=304;i<338;i++){ if(i==331) continue; sd->status.skill[i].lv=skill_get_max(i); } + for(i=355;i<411;i++) + sd->status.skill[i].lv=skill_get_max(i); + for(i=475;i<480;i++) + sd->status.skill[i].lv=skill_get_max(i); } else { for(i=0;(id=skill_tree[s][c][i].id)>0;i++){ if(sd->status.skill[id].id==0 && (!(skill_get_inf2(id)&0x01) || battle_config.quest_skill_learn) ) { sd->status.skill[id].id = id; // celest // sd->status.skill[id].lv=skill_get_max(id); - sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class); // celest + sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_); // celest } } } - pc_calcstatus(sd,0); + status_calc_pc(sd,0); return 0; } @@ -5118,9 +4413,9 @@ int pc_allskillup(struct map_session_data *sd) int pc_resetlvl(struct map_session_data* sd,int type) { int i; - + nullpo_retr(0, sd); - + for(i=1;i<MAX_SKILL;i++){ sd->status.skill[i].lv = 0; } @@ -5140,8 +4435,11 @@ int pc_resetlvl(struct map_session_data* sd,int type) sd->status.int_=1; sd->status.dex=1; sd->status.luk=1; - if(sd->status.class == 4001) - sd->status.status_point=88; + if(sd->status.class_ == 4001) + sd->status.status_point=100; // not 88 [celest] + // give platinum skills upon changing + pc_skill(sd,142,1,0); + pc_skill(sd,143,1,0); } if(type == 2){ @@ -5158,7 +4456,7 @@ int pc_resetlvl(struct map_session_data* sd,int type) if(type == 4){ sd->status.job_level=1; sd->status.job_exp=0; - } + } clif_updatestatus(sd,SP_STATUSPOINT); clif_updatestatus(sd,SP_STR); @@ -5184,11 +4482,11 @@ int pc_resetlvl(struct map_session_data* sd,int type) for(i=0;i<11;i++) { // unequip items that can't be equipped by base 1 [Valaris] if(sd->equip_index[i] >= 0) if(!pc_isequip(sd,sd->equip_index[i])) - pc_unequipitem(sd,sd->equip_index[i],1,BF_NORMAL); + pc_unequipitem(sd,sd->equip_index[i],2); } clif_skillinfoblock(sd); - pc_calcstatus(sd,0); + status_calc_pc(sd,0); return 0; } @@ -5200,14 +4498,17 @@ int pc_resetstate(struct map_session_data* sd) { #define sumsp(a) ((a)*((a-2)/10+2) - 5*((a-2)/10)*((a-2)/10) - 6*((a-2)/10) -2) // int add=0; // Removed by Dexity + int lv; nullpo_retr(0, sd); + // allow it to just read the last entry [celest] + lv = sd->status.base_level < MAX_LEVEL ? sd->status.base_level : MAX_LEVEL - 1; // New statpoint table used here - Dexity - sd->status.status_point = atoi (statp[sd->status.base_level - 1]); - if(sd->status.class >= 4001 && sd->status.class <= 4024) - sd->status.status_point+=40; -// End addition + sd->status.status_point = statp[lv]; + if(sd->status.class_ >= 4001 && sd->status.class_ <= 4024) + sd->status.status_point+=52; // extra 52+48=100 stat points +// End addition // Removed by Dexity - old count // add += sumsp(sd->status.str); @@ -5241,7 +4542,7 @@ int pc_resetstate(struct map_session_data* sd) clif_updatestatus(sd,SP_UDEX); clif_updatestatus(sd,SP_ULUK); // End Addition - pc_calcstatus(sd,0); + status_calc_pc(sd,0); return 0; } @@ -5257,7 +4558,8 @@ int pc_resetskill(struct map_session_data* sd) nullpo_retr(0, sd); for(i=1;i<MAX_SKILL;i++){ - if( (skill = pc_checkskill(sd,i)) > 0) { + skill = ( i >= 10000 ) ? pc_checkskill(sd,i) : sd->status.skill[i].lv; + if( skill > 0) { if(!(skill_get_inf2(i)&0x01) || battle_config.quest_skill_learn) { if(!sd->status.skill[i].flag) sd->status.skill_point += skill; @@ -5269,13 +4571,13 @@ int pc_resetskill(struct map_session_data* sd) else if(battle_config.quest_skill_reset) sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; - } - else + } else { sd->status.skill[i].lv = 0; + } } clif_updatestatus(sd,SP_SKILLPOINT); clif_skillinfoblock(sd); - pc_calcstatus(sd,0); + status_calc_pc(sd,0); return 0; } @@ -5292,7 +4594,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) nullpo_retr(0, sd); //?¶‚â—{Žq‚Ìꇂ̌³‚ÌE‹Æ‚ðŽZo‚·‚é - s_class = pc_calc_base_job(sd->status.class); + s_class = pc_calc_base_job(sd->status.class_); // ?‚ÉŽ€‚ñ‚Å‚¢‚½‚ç–³? if(pc_isdead(sd)) return 0; @@ -5303,11 +4605,16 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) } // ? ‚¢‚Ä‚¢‚½‚ç‘«‚ðŽ~‚ß‚é - if(sd->sc_data[SC_ENDURE].timer == -1 && sd->sc_data[SC_BERSERK].timer && !sd->special_state.infinite_endure) - pc_stop_walking(sd,3); - else if(sd->sc_data[SC_ENDURE].timer != -1 && src->type==BL_MOB) // [Celest] - if((--sd->sc_data[SC_ENDURE].val2) <= 0) - skill_status_change_end(&sd->bl, SC_ENDURE, -1); + if (sd->sc_data) { + if (sd->sc_data[SC_BERSERK].timer != -1 || + sd->special_state.infinite_endure) + ; // do nothing + else if (sd->sc_data[SC_ENDURE].timer != -1 && (src != NULL && src->type == BL_MOB) && !map[sd->bl.m].flag.gvg) { + if ((--sd->sc_data[SC_ENDURE].val2) < 0) + status_change_end(&sd->bl, SC_ENDURE, -1); + } else pc_stop_walking(sd,3); + } + // ‰‰‘t/ƒ_ƒ“ƒX‚Ì’†? if(damage > sd->status.max_hp>>2) skill_stop_dancing(&sd->bl,0); @@ -5317,22 +4624,23 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) pet_target_check(sd,src,1); if (sd->sc_data[SC_TRICKDEAD].timer != -1) - skill_status_change_end(&sd->bl, SC_TRICKDEAD, -1); + status_change_end(&sd->bl, SC_TRICKDEAD, -1); if(sd->status.option&2) - skill_status_change_end(&sd->bl, SC_HIDING, -1); + status_change_end(&sd->bl, SC_HIDING, -1); if(sd->status.option&4) - skill_status_change_end(&sd->bl, SC_CLOAKING, -1); - if(sd->status.option&16386) - skill_status_change_end(&sd->bl, SC_CHASEWALK, -1); + status_change_end(&sd->bl, SC_CLOAKING, -1); + if(sd->status.option&16384) + status_change_end(&sd->bl, SC_CHASEWALK, -1); if(sd->status.hp>0){ // ‚Ü‚¾¶‚«‚Ä‚¢‚é‚È‚çHPXV clif_updatestatus(sd,SP_HP); - if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 && + //if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 && + if(sd->status.hp<sd->status.max_hp>>2 && sd->sc_data[SC_AUTOBERSERK].timer != -1 && (sd->sc_data[SC_PROVOKE].timer==-1 || sd->sc_data[SC_PROVOKE].val2==0 )) // ƒI?ƒgƒo?ƒT?ƒN?“® - skill_status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0); + status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0); sd->canlog_tick = gettick(); @@ -5344,7 +4652,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) return 0; } sd->status.hp = 0; - pc_setdead(sd); + //pc_setdead(sd); if(sd->vender_id) vending_closevending(sd); @@ -5360,45 +4668,104 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) pc_stop_walking(sd,0); skill_castcancel(&sd->bl,0); // ‰r¥‚Ì’†Ž~ clif_clearchar_area(&sd->bl,1); - skill_unit_out_all(&sd->bl,gettick(),1); + pc_setdead(sd); + skill_unit_move(&sd->bl,gettick(),0); if(sd->sc_data[SC_BLADESTOP].timer!=-1)//”’n‚ÍŽ–‘O‚ɉðœ - skill_status_change_end(&sd->bl,SC_BLADESTOP,-1); + status_change_end(&sd->bl,SC_BLADESTOP,-1); pc_setglobalreg(sd,"PC_DIE_COUNTER",++sd->die_counter); //Ž€‚ɃJƒEƒ“ƒ^?‘‚«?‚Ý - skill_status_change_clear(&sd->bl,0); // ƒXƒe?ƒ^ƒXˆÙí‚ð‰ðœ‚·‚é + status_change_clear(&sd->bl,0); // ƒXƒe?ƒ^ƒXˆÙí‚ð‰ðœ‚·‚é clif_updatestatus(sd,SP_HP); - pc_calcstatus(sd,0); + status_calc_pc(sd,0); + + if (src && src->type == BL_PC) { + struct map_session_data *ssd = (struct map_session_data *)src; + if (ssd) { + if (sd->state.event_death) + pc_setglobalreg(sd,"killerrid",(ssd->status.account_id)); + if (ssd->state.event_kill) { + if (script_config.event_script_type == 0) { + struct npc_data *npc; + if ((npc = npc_name2id(script_config.kill_event_name))) { + run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCKillNPC + sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.kill_event_name); + ShowStatus(tmp_output); + } + } else { + sprintf (tmp_output, "%d '"CL_WHITE"%s"CL_RESET"' events executed.\n", + npc_event_doall_id(script_config.kill_event_name, sd->bl.id), script_config.kill_event_name); + ShowStatus(tmp_output); + } + } + } + } + + if (sd->state.event_death) { + if (script_config.event_script_type == 0) { + struct npc_data *npc; + if ((npc = npc_name2id(script_config.die_event_name))) { + run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCDeathNPC + sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.die_event_name); + ShowStatus(tmp_output); + } + } else { + sprintf (tmp_output, "%d '"CL_WHITE"%s"CL_RESET"' events executed.\n", + npc_event_doall_id(script_config.die_event_name, sd->bl.id), script_config.die_event_name); + ShowStatus(tmp_output); + } + } + + if(battle_config.bone_drop==2 + || (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp)){ // ƒhƒNƒƒhƒƒbƒv + struct item item_tmp; + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid=7005; + item_tmp.identify=1; + item_tmp.card[0]=0x00fe; + item_tmp.card[1]=0; + *((unsigned long *)(&item_tmp.card[2]))=sd->char_id; /* ƒLƒƒƒ‰ID */ + map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); + } + + // activate Steel body if a super novice dies at 99+% exp [celest] + if (s_class.job == 23) { + if ((i=pc_nextbaseexp(sd))<=0) + i=sd->status.base_exp; + if (i>0 && (j=sd->status.base_exp*1000/i)>=990 && j<=1000) + sd->state.snovice_flag = 4; + } for(i=0;i<5;i++) if(sd->dev.val1[i]){ - skill_status_change_end(&map_id2sd(sd->dev.val1[i])->bl,SC_DEVOTION,-1); + status_change_end(&map_id2sd(sd->dev.val1[i])->bl,SC_DEVOTION,-1); sd->dev.val1[i] = sd->dev.val2[i]=0; } if(battle_config.death_penalty_type>0) { // changed penalty options, added death by player if pk_mode [Valaris] - if(sd->status.class != 0 && !map[sd->bl.m].flag.nopenalty && !map[sd->bl.m].flag.gvg){ // only novices will recieve no penalty + if(sd->status.class_ != 0 && !map[sd->bl.m].flag.nopenalty && !map[sd->bl.m].flag.gvg && // only novices will recieve no penalty + !(sd->sc_count && sd->sc_data[SC_BABY].timer!=-1)) { if(battle_config.death_penalty_type==1 && battle_config.death_penalty_base > 0) - sd->status.base_exp -= (double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000; + sd->status.base_exp -= (int) ((double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000); if(battle_config.pk_mode && src && src->type==BL_PC) - sd->status.base_exp -= (double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000; + sd->status.base_exp -= (int) ((double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000); else if(battle_config.death_penalty_type==2 && battle_config.death_penalty_base > 0) { if(pc_nextbaseexp(sd) > 0) - sd->status.base_exp -= (double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000; + sd->status.base_exp -= (int) ((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000); if(battle_config.pk_mode && src && src->type==BL_PC) - sd->status.base_exp -= (double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000; + sd->status.base_exp -= (int) ((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000); } if(sd->status.base_exp < 0) sd->status.base_exp = 0; clif_updatestatus(sd,SP_BASEEXP); if(battle_config.death_penalty_type==1 && battle_config.death_penalty_job > 0) - sd->status.job_exp -= (double)pc_nextjobexp(sd) * (double)battle_config.death_penalty_job/10000; + sd->status.job_exp -= (int) ((double)pc_nextjobexp(sd) * (double)battle_config.death_penalty_job/10000); if(battle_config.pk_mode && src && src->type==BL_PC) - sd->status.job_exp -= (double)pc_nextjobexp(sd) * (double)battle_config.death_penalty_job/10000; + sd->status.job_exp -= (int) ((double)pc_nextjobexp(sd) * (double)battle_config.death_penalty_job/10000); else if(battle_config.death_penalty_type==2 && battle_config.death_penalty_job > 0) { if(pc_nextjobexp(sd) > 0) - sd->status.job_exp -= (double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000; + sd->status.job_exp -= (int) ((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000); if(battle_config.pk_mode && src && src->type==BL_PC) - sd->status.job_exp -= (double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000; + sd->status.job_exp -= (int) ((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000); } if(sd->status.job_exp < 0) sd->status.job_exp = 0; @@ -5415,7 +4782,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) if(md && md->state.state!=MS_DEAD && md->level < 99) { clif_misceffect(&md->bl,0); md->level++; - md->hp+=sd->status.max_hp*.1; + md->hp+=(int) (sd->status.max_hp*.1); } } @@ -5450,7 +4817,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) int n = eq_n[rand()%eq_num];//ŠY?ƒAƒCƒeƒ€‚Ì’†‚©‚烉ƒ“ƒ_ƒ€ if(rand()%10000 < per){ if(sd->status.inventory[n].equip) - pc_unequipitem(sd,n,0,BF_NORMAL); + pc_unequipitem(sd,n,3); pc_dropitem(sd,n,1); } } @@ -5463,7 +4830,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) || (type == 2 && sd->status.inventory[i].equip) || type == 3) ){ if(sd->status.inventory[i].equip) - pc_unequipitem(sd,i,0,BF_NORMAL); + pc_unequipitem(sd,i,3); pc_dropitem(sd,i,1); break; } @@ -5510,8 +4877,8 @@ int pc_readparam(struct map_session_data *sd,int type) { int val=0; struct pc_base_job s_class; - - s_class = pc_calc_base_job(sd->status.class); + + s_class = pc_calc_base_job(sd->status.class_); nullpo_retr(0, sd); @@ -5535,7 +4902,7 @@ int pc_readparam(struct map_session_data *sd,int type) if(val>=24 && val < 45) val+=3978; else - val= sd->status.class; + val= sd->status.class_; break; case SP_BASEJOB: val= s_class.job; @@ -5594,6 +4961,12 @@ int pc_readparam(struct map_session_data *sd,int type) case SP_LUK: val= sd->status.luk; break; + case SP_KARMA: // celest + val = sd->status.karma; + break; + case SP_MANNER: + val = sd->status.manner; + break; case SP_FAME: val= sd->fame; break; @@ -5613,7 +4986,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val) nullpo_retr(0, sd); - s_class = pc_calc_base_job(sd->status.class); + s_class = pc_calc_base_job(sd->status.class_); switch(type){ case SP_BASELEVEL: @@ -5627,24 +5000,27 @@ int pc_setparam(struct map_session_data *sd,int type,int val) clif_updatestatus(sd, SP_NEXTBASEEXP); clif_updatestatus(sd, SP_STATUSPOINT); clif_updatestatus(sd, SP_BASEEXP); - pc_calcstatus(sd, 0); + status_calc_pc(sd, 0); pc_heal(sd, sd->status.max_hp, sd->status.max_sp); break; case SP_JOBLEVEL: - if (sd->status.class == 0) + if (s_class.job == 0) up_level -= 40; - if ((sd->status.class == 23) || (sd->status.class >= 4001 && sd->status.class <= 4022)) + // super novices can go up to 99 [celest] + else if (s_class.job == 23) + up_level += 49; + else if (sd->status.class_ >= 4008 && sd->status.class_ <= 4022) up_level += 20; if (val >= sd->status.job_level) { if (val > up_level)val = up_level; sd->status.skill_point += (val-sd->status.job_level); - sd->status.job_level = val; + sd->status.job_level = val; sd->status.job_exp = 0; clif_updatestatus(sd, SP_JOBLEVEL); clif_updatestatus(sd, SP_NEXTJOBEXP); clif_updatestatus(sd, SP_JOBEXP); clif_updatestatus(sd, SP_SKILLPOINT); - pc_calcstatus(sd, 0); + status_calc_pc(sd, 0); clif_misceffect(&sd->bl, 1); } else { sd->status.job_level = val; @@ -5652,7 +5028,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val) clif_updatestatus(sd, SP_JOBLEVEL); clif_updatestatus(sd, SP_NEXTJOBEXP); clif_updatestatus(sd, SP_JOBEXP); - pc_calcstatus(sd, 0); + status_calc_pc(sd, 0); } clif_updatestatus(sd,type); break; @@ -5663,7 +5039,21 @@ int pc_setparam(struct map_session_data *sd,int type,int val) sd->status.status_point = val; break; case SP_ZENY: - sd->status.zeny = val; + if(val <= MAX_ZENY) { + // MAX_ZENY ˆÈ‰º‚È‚ç‘ã“ü + sd->status.zeny = val; + } else { + if(sd->status.zeny > val) { + // Zeny ‚ªŒ¸‚µ‚Ä‚¢‚é‚È‚ç‘ã“ü + sd->status.zeny = val; + } else if(sd->status.zeny <= MAX_ZENY) { + // Zeny ‚ª‘‰Á‚µ‚Ä‚¢‚ÄAŒ»Ý‚Ì’l‚ªMAX_ZENY ˆÈ‰º‚È‚çMAX_ZENY + sd->status.zeny = MAX_ZENY; + } else { + // Zeny ‚ª‘‰Á‚µ‚Ä‚¢‚ÄAŒ»Ý‚Ì’l‚ªMAX_ZENY ‚æ‚艺‚Ȃ瑉Á•ª‚𖳎‹ + ; + } + } break; case SP_BASEEXP: if(pc_nextbaseexp(sd) > 0) { @@ -5720,6 +5110,12 @@ int pc_setparam(struct map_session_data *sd,int type,int val) case SP_LUK: sd->status.luk = val; break; + case SP_KARMA: + sd->status.karma = val; + break; + case SP_MANNER: + sd->status.manner = val; + break; case SP_FAME: sd->fame = val; break; @@ -5749,7 +5145,7 @@ int pc_heal(struct map_session_data *sd,int hp,int sp) sp = 0; } - if(sd->sc_data && sd->sc_data[SC_BERSERK].timer!=-1) //ƒo?ƒT?ƒN’†‚͉ñ•œ‚³‚¹‚È‚¢‚炵‚¢ + if(sd->sc_count && sd->sc_data[SC_BERSERK].timer!=-1) //ƒo?ƒT?ƒN’†‚͉ñ•œ‚³‚¹‚È‚¢‚炵‚¢ return 0; if(hp+sd->status.hp>sd->status.max_hp) @@ -5784,13 +5180,13 @@ int pc_heal(struct map_session_data *sd,int hp,int sp) */ int pc_itemheal(struct map_session_data *sd,int hp,int sp) { - int bonus; + int bonus, type = 0; // if(battle_config.battle_log) // printf("heal %d %d\n",hp,sp); nullpo_retr(0, sd); - if(sd->sc_data && sd->sc_data[SC_GOSPEL].timer!=-1) //ƒo?ƒT?ƒN’†‚͉ñ•œ‚³‚¹‚È‚¢‚炵‚¢ + if(sd->sc_count && sd->sc_data[SC_GOSPEL].timer!=-1) //ƒo?ƒT?ƒN’†‚͉ñ•œ‚³‚¹‚È‚¢‚炵‚¢ return 0; if(sd->state.potionpitcher_flag) { @@ -5807,19 +5203,33 @@ int pc_itemheal(struct map_session_data *sd,int hp,int sp) if(sp > 0) sp = 0; } + + if (sd->itemid >= 501 && sd->itemid <= 505) + type = 1; // potions + else if (sd->itemid >= 507 && sd->itemid <= 510) + type = 2; // herbs + else if (sd->itemid >= 512 && sd->itemid <= 516) + type = 3; // fruits + else if (sd->itemid == 517 || sd->itemid == 528) + type = 4; // meat + else if (sd->itemid == 529 || sd->itemid == 530) + type = 5; // candy + else if (sd->itemid >= 531 && sd->itemid <= 534) + type = 6; // juice + else if (sd->itemid == 544 || sd->itemid == 551) + type = 7; // sashimi + if(hp > 0) { - bonus = (sd->paramc[2]<<1) + 100 + pc_checkskill(sd,SM_RECOVERY)*10; - if(bonus != 100) - hp = hp * bonus / 100; - bonus = 100 + pc_checkskill(sd,AM_LEARNINGPOTION)*5; + bonus = (sd->paramc[2]<<1) + 100 + pc_checkskill(sd,SM_RECOVERY)*10 + + pc_checkskill(sd,AM_LEARNINGPOTION)*5; + if (type > 0) + bonus += sd->itemhealrate[type - 1]; if(bonus != 100) hp = hp * bonus / 100; } if(sp > 0) { - bonus = (sd->paramc[3]<<1) + 100 + pc_checkskill(sd,MG_SRECOVERY)*10; - if(bonus != 100) - sp = sp * bonus / 100; - bonus = 100 + pc_checkskill(sd,AM_LEARNINGPOTION)*5; + bonus = (sd->paramc[3]<<1) + 100 + pc_checkskill(sd,MG_SRECOVERY)*10 + + pc_checkskill(sd,AM_LEARNINGPOTION)*5; if(bonus != 100) sp = sp * bonus / 100; } @@ -5920,13 +5330,13 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) int i; int b_class = 0; //?¶‚â—{Žq‚Ìꇂ̌³‚ÌE‹Æ‚ðŽZo‚·‚é - struct pc_base_job s_class = pc_calc_base_job(sd->status.class); - + struct pc_base_job s_class = pc_calc_base_job(sd->status.class_); + nullpo_retr(0, sd); if (upper < 0 || upper > 2) //Œ»Ý?¶‚©‚Ç‚¤‚©‚ð”»?‚·‚é upper = s_class.upper; - + b_class = job; //’ÊíE‚È‚çjob‚»‚̂܂ñ‚Ü if (job < 23) { if (upper == 1) @@ -5948,7 +5358,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) if((sd->status.sex == 0 && job == 19) || (sd->status.sex == 1 && job == 20) || // not needed [celest] //(sd->status.sex == 0 && job == 4020) || (sd->status.sex == 1 && job == 4021) || - job == 22 || sd->status.class == b_class) //Š‚Íƒo?ƒh‚ɂȂê‚È‚¢A‰‚̓_ƒ“ƒT?‚ɂȂê‚È‚¢AŒ‹¥ˆßÖ‚à‚¨?‚è + job == 22 || sd->status.class_ == b_class) //Š‚Íƒo?ƒh‚ɂȂê‚È‚¢A‰‚̓_ƒ“ƒT?‚ɂȂê‚È‚¢AŒ‹¥ˆßÖ‚à‚¨?‚è return 1; // check if we are changing from 1st to 2nd job @@ -5958,12 +5368,12 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) else sd->change_level = 40; } - else - sd->change_level = 0; + else + sd->change_level = 0; - pc_setglobalreg (sd, "jobchange_level", sd->change_level); - - sd->status.class = sd->view_class = b_class; + pc_setglobalreg (sd, "jobchange_level", sd->change_level); + + sd->status.class_ = sd->view_class = b_class; sd->status.job_level=1; sd->status.job_exp=0; @@ -5974,7 +5384,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) for(i=0;i<11;i++) { if(sd->equip_index[i] >= 0) if(!pc_isequip(sd,sd->equip_index[i])) - pc_unequipitem(sd,sd->equip_index[i],1,BF_NORMAL); // ?”õŠO‚µ + pc_unequipitem(sd,sd->equip_index[i],2); // ?”õŠO‚µ } clif_changelook(&sd->bl,LOOK_BASE,sd->view_class); // move sprite update to prevent client crashes with incompatible equipment [Valaris] @@ -5983,18 +5393,18 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) if(battle_config.muting_players && sd->status.manner < 0) clif_changestatus(&sd->bl,SP_MANNER,sd->status.manner); - pc_calcstatus(sd,0); + status_calc_pc(sd,0); pc_checkallowskill(sd); pc_equiplookall(sd); clif_equiplist(sd); if(pc_isriding(sd)) { // remove peco status if changing into invalid class [Valaris] - if(!(pc_checkskill(sd,KN_RIDING))) + if(!(pc_checkskill(sd,KN_RIDING))) pc_setoption(sd,sd->status.option|-0x0000); if(pc_checkskill(sd,KN_RIDING)>0) pc_setriding(sd); } - + return 0; } @@ -6071,7 +5481,7 @@ int pc_setoption(struct map_session_data *sd,int type) sd->status.option=type; clif_changeoption(&sd->bl); - pc_calcstatus(sd,0); + status_calc_pc(sd,0); return 0; } @@ -6129,23 +5539,35 @@ int pc_setriding(struct map_session_data *sd) if((pc_checkskill(sd,KN_RIDING)>0)){ // ƒ‰ƒCƒfƒBƒ“ƒOƒXƒLƒ‹ŠŽ pc_setoption(sd,sd->status.option|0x0020); - if(sd->status.class==7) - sd->status.class=sd->view_class=13; - - if(sd->status.class==14) - sd->status.class=sd->view_class=21; - - if(sd->status.class==4008) - sd->status.class=sd->view_class=4014; - - if(sd->status.class==4015) - sd->status.class=sd->view_class=4022; + if(sd->status.class_==7) + sd->status.class_=sd->view_class=13; + + if(sd->status.class_==14) + sd->status.class_=sd->view_class=21; + + if(sd->status.class_==4008) + sd->status.class_=sd->view_class=4014; + + if(sd->status.class_==4015) + sd->status.class_=sd->view_class=4022; } return 0; } /*========================================== + * ƒAƒCƒeƒ€ƒhƒƒbƒv‰Â•s‰Â”»’è + *------------------------------------------ + */ +int pc_candrop(struct map_session_data *sd,int item_id) +{ + int level; + if((level=pc_isGM(sd))>0 && level < battle_config.gm_can_drop_lv) // search only once [Celest] + return 1; + return 0; +} + +/*========================================== * script—p??‚Ì’l‚ð?‚Þ *------------------------------------------ */ @@ -6178,14 +5600,7 @@ int pc_setreg(struct map_session_data *sd,int reg,int val) } } sd->reg_num++; - sd->reg = realloc(sd->reg, sizeof(*(sd->reg)) * sd->reg_num); - if (sd->reg == NULL){ - printf("out of memory : pc_setreg\n"); - exit(1); - } -/* memset(sd->reg + (sd->reg_num - 1) * sizeof(*(sd->reg)), 0, - sizeof(*(sd->reg))); -*/ + sd->reg = (struct script_reg *) aRealloc(sd->reg, sizeof(*(sd->reg)) * sd->reg_num); sd->reg[i].index = reg; sd->reg[i].data = val; @@ -6229,7 +5644,7 @@ int pc_setregstr(struct map_session_data *sd,int reg,char *str) return 0; } sd->regstr_num++; - sd->regstr = realloc(sd->regstr, sizeof(sd->regstr[0]) * sd->regstr_num); + sd->regstr = (struct script_regstr *) aRealloc(sd->regstr, sizeof(sd->regstr[0]) * sd->regstr_num); if(sd->regstr==NULL){ printf("out of memory : pc_setreg\n"); exit(1); @@ -6271,11 +5686,18 @@ int pc_setglobalreg(struct map_session_data *sd,char *reg,int val) nullpo_retr(0, sd); - //PC_DIE_COUNTER‚ªƒXƒNƒŠƒvƒg‚ȂǂÅ?X‚³‚ê‚½Žž‚Ì?— + //PC_DIE_COUNTER‚ªƒXƒNƒŠƒvƒg‚ȂǂÅ?X‚³‚ꂽŽbÌ?— if(strcmp(reg,"PC_DIE_COUNTER") == 0 && sd->die_counter != val){ sd->die_counter = val; - pc_calcstatus(sd,0); + status_calc_pc(sd,0); + } else if(strcmp(reg,script_config.die_event_name) == 0){ + sd->state.event_death = val; + } else if(strcmp(reg,script_config.kill_event_name) == 0){ + sd->state.event_kill = val; + } else if(strcmp(reg,script_config.logout_event_name) == 0){ + sd->state.event_disconnect = val; } + if(val==0){ for(i=0;i<sd->status.global_reg_num;i++){ if(strcmp(sd->status.global_reg[i].str,reg)==0){ @@ -6331,6 +5753,12 @@ int pc_setaccountreg(struct map_session_data *sd,char *reg,int val) nullpo_retr(0, sd); + if (sd->status.account_reg_num == -1) { + if(battle_config.error_log) + printf("pc_setaccountreg : refusing to set until vars are received\n"); + return 1; + } + if(val==0){ for(i=0;i<sd->status.account_reg_num;i++){ if(strcmp(sd->status.account_reg[i].str,reg)==0){ @@ -6418,29 +5846,6 @@ int pc_setaccountreg2(struct map_session_data *sd,char *reg,int val) return 1; } -/*========================================== - * ¸?¬Œ÷—¦ - *------------------------------------------ - */ -int pc_percentrefinery(struct map_session_data *sd,struct item *item) -{ - int percent; - - nullpo_retr(0, item); - percent=percentrefinery[itemdb_wlv(item->nameid)][(int)item->refine]; - - percent += pc_checkskill(sd,BS_WEAPONRESEARCH); // •Ší?‹†ƒXƒLƒ‹ŠŽ - - // Šm—¦‚Ì—L?”Í?ƒ`ƒFƒbƒN - if( percent > 100 ){ - percent = 100; - } - if( percent < 0 ){ - percent = 0; - } - - return percent; -} /*========================================== * ƒCƒxƒ“ƒgƒ^ƒCƒ}??— @@ -6449,6 +5854,7 @@ int pc_percentrefinery(struct map_session_data *sd,struct item *item) int pc_eventtimer(int tid,unsigned int tick,int id,int data) { struct map_session_data *sd=map_id2sd(id); + char *p = (char *)data; int i; if(sd==NULL) return 0; @@ -6456,11 +5862,11 @@ int pc_eventtimer(int tid,unsigned int tick,int id,int data) for(i=0;i<MAX_EVENTTIMER;i++){ if( sd->eventtimer[i]==tid ){ sd->eventtimer[i]=-1; - npc_event(sd,(const char *)data,0); + npc_event(sd,p,0); break; } } - free((void *)data); + aFree(p); if(i==MAX_EVENTTIMER) { if(battle_config.error_log) printf("pc_eventtimer: no such event timer\n"); @@ -6483,10 +5889,12 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name) if( sd->eventtimer[i]==-1 ) break; if(i<MAX_EVENTTIMER){ - char *evname=(char *)aCalloc(24,sizeof(char)); - memcpy(evname,name,24); + char *evname=strdup(name); + //char *evname=(char *)aMallocA((strlen(name)+1)*sizeof(char)); + //memcpy(evname,name,(strlen(name)+1)); sd->eventtimer[i]=add_timer(gettick()+tick, pc_eventtimer,sd->bl.id,(int)evname); + sd->eventcount++; } return 0; @@ -6502,12 +5910,19 @@ int pc_deleventtimer(struct map_session_data *sd,const char *name) nullpo_retr(0, sd); + if (sd->eventcount <= 0) + return 0; + for(i=0;i<MAX_EVENTTIMER;i++) - if( sd->eventtimer[i]!=-1 && strcmp( - (char *)(get_timer(sd->eventtimer[i])->data), name)==0 ){ + if( sd->eventtimer[i]!=-1 ) { + char *p = (char *)(get_timer(sd->eventtimer[i])->data); + if(strcmp(p, name)==0) { delete_timer(sd->eventtimer[i],pc_eventtimer); sd->eventtimer[i]=-1; + sd->eventcount--; + aFree(p); break; + } } return 0; @@ -6543,10 +5958,15 @@ int pc_cleareventtimer(struct map_session_data *sd) nullpo_retr(0, sd); + if (sd->eventcount <= 0) + return 0; + for(i=0;i<MAX_EVENTTIMER;i++) if( sd->eventtimer[i]!=-1 ){ + char *p = (char *)(get_timer(sd->eventtimer[i])->data); delete_timer(sd->eventtimer[i],pc_eventtimer); sd->eventtimer[i]=-1; + aFree(p); } return 0; @@ -6579,7 +5999,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos) // -- moonsoul (if player is berserk then cannot equip) // - if(sd->sc_data[SC_BERSERK].timer!=-1){ + if(sd->sc_count && sd->sc_data[SC_BERSERK].timer!=-1){ clif_equipitemack(sd,n,0,0); // fail return 0; } @@ -6597,7 +6017,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos) // “ñ“—¬?— if ((pos==0x22) // ˆê?A?”õ—v‹‰ÓŠ‚ª“ñ“—¬•Ší‚©ƒ`ƒFƒbƒN‚·‚é && (id->equip==2) // ? Žè•Ší - && (pc_checkskill(sd, AS_LEFT) > 0 || pc_calc_base_job2(sd->status.class) == 12) ) // ¶ŽèC?—L + && (pc_checkskill(sd, AS_LEFT) > 0 || pc_calc_base_job2(sd->status.class_) == 12) ) // ¶ŽèC?—L { int tpos=0; if(sd->equip_index[8] >= 0) @@ -6611,7 +6031,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos) arrow=pc_search_inventory(sd,pc_checkequip(sd,9)); // Added by RoVeRT for(i=0;i<11;i++) { if(sd->equip_index[i] >= 0 && sd->status.inventory[sd->equip_index[i]].equip&pos) { - pc_unequipitem(sd,sd->equip_index[i],1,BF_NORMAL); + pc_unequipitem(sd,sd->equip_index[i],2); } } // ‹|–î?”õ @@ -6680,40 +6100,47 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos) clif_changelook(&sd->bl,LOOK_SHOES,0); pc_checkallowskill(sd); // ?”õ•i‚ŃXƒLƒ‹‚©‰ðœ‚³‚ê‚é‚©ƒ`ƒFƒbƒN - if (itemdb_look(sd->status.inventory[n].nameid) == 11 && arrow){ // Added by RoVeRT + if (itemdb_look(sd->status.inventory[n].nameid) == 11 && (arrow >= 0)){ // Added by RoVeRT clif_arrowequip(sd,arrow); sd->status.inventory[arrow].equip=32768; } - pc_calcstatus(sd,0); + status_calc_pc(sd,0); if(sd->special_state.infinite_endure) { if(sd->sc_data[SC_ENDURE].timer == -1) - skill_status_change_start(&sd->bl,SC_ENDURE,10,1,0,0,0,0); + status_change_start(&sd->bl,SC_ENDURE,10,1,0,0,0,0); } else { - if(sd->sc_data[SC_ENDURE].timer != -1 && sd->sc_data[SC_ENDURE].val2) - skill_status_change_end(&sd->bl,SC_ENDURE,-1); + if(sd->sc_count && sd->sc_data[SC_ENDURE].timer != -1 && sd->sc_data[SC_ENDURE].val2) + status_change_end(&sd->bl,SC_ENDURE,-1); } - if(sd->sc_data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele)) - skill_status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1); - if(sd->sc_data[SC_DANCING].timer!=-1 && (sd->status.weapon != 13 && sd->status.weapon !=14)) - skill_stop_dancing(&sd->bl,0); + if(sd->sc_count) { + if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele)) + status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1); + if(sd->sc_data[SC_DANCING].timer!=-1 && (sd->status.weapon != 13 && sd->status.weapon !=14)) + skill_stop_dancing(&sd->bl,0); + } return 0; } /*========================================== * ? ”õ‚µ‚½•¨‚ðŠO‚· + * type: + * 0 - only unequip + * 1 - calculate status after unequipping + * 2 - force unequip *------------------------------------------ */ -int pc_unequipitem(struct map_session_data *sd,int n,int type, int flag) +int pc_unequipitem(struct map_session_data *sd,int n,int flag) { - nullpo_retr(0, sd); + short hp = 0, sp = 0; + nullpo_retr(0, sd); // -- moonsoul (if player is berserk then cannot unequip) // - if(!flag && sd->sc_data[SC_BERSERK].timer!=-1){ + if(flag<2 && sd->sc_count && (sd->sc_data[SC_BLADESTOP].timer!=-1 || sd->sc_data[SC_BERSERK].timer!=-1)){ clif_unequipitemack(sd,n,0,0); return 0; } @@ -6723,8 +6150,17 @@ int pc_unequipitem(struct map_session_data *sd,int n,int type, int flag) if(sd->status.inventory[n].equip){ int i; for(i=0;i<11;i++) { - if(sd->status.inventory[n].equip & equip_pos[i]) + if(sd->status.inventory[n].equip & equip_pos[i]) { sd->equip_index[i] = -1; + if(sd->unequip_losehp[i] > 0) { + hp += sd->unequip_losehp[i]; + sd->unequip_losehp[i] = 0; + } + if(sd->unequip_losesp[i] > 0) { + sp += sd->unequip_losesp[i]; + sd->unequip_losesp[i] = 0; + } + } } if(sd->status.inventory[n].equip & 0x0002) { sd->weapontype1 = 0; @@ -6752,23 +6188,37 @@ int pc_unequipitem(struct map_session_data *sd,int n,int type, int flag) if(sd->status.inventory[n].equip & 0x0040) clif_changelook(&sd->bl,LOOK_SHOES,0); - if(sd->sc_data[SC_BROKNWEAPON].timer != -1 && sd->status.inventory[n].equip & 0x0002 && - sd->status.inventory[i].attribute==1) - skill_status_change_end(&sd->bl,SC_BROKNWEAPON,-1); + if(sd->sc_count) { + if (sd->sc_data[SC_BROKNWEAPON].timer != -1 && sd->status.inventory[n].equip & 0x0002 && + sd->status.inventory[n].attribute == 1) + status_change_end(&sd->bl,SC_BROKNWEAPON,-1); + if(sd->sc_data[SC_BROKNARMOR].timer != -1 && sd->status.inventory[n].equip & 0x0010 && + sd->status.inventory[n].attribute == 1) + status_change_end(&sd->bl,SC_BROKNARMOR,-1); + } clif_unequipitemack(sd,n,sd->status.inventory[n].equip,1); sd->status.inventory[n].equip=0; - if(!type) + if(flag&1) pc_checkallowskill(sd); if(sd->weapontype1 == 0 && sd->weapontype2 == 0) - skill_encchant_eremental_end(&sd->bl,-1); //•ŠíŽ‚¿¾‚¦‚Í–³?Œ‚Å?«•t?‰ðœ + skill_enchant_elemental_end(&sd->bl,-1); //•ŠíŽ‚¿¾‚¦‚Í–³?Œ‚Å?«•t?‰ðœ } else { clif_unequipitemack(sd,n,0,0); } - if(!type) { - pc_calcstatus(sd,0); - if(sd->sc_data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele)) - skill_status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1); + + if(flag&1) { + status_calc_pc(sd,0); + if(sd->sc_count && sd->sc_data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele)) + status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1); + } + + if (hp > 0 || sp > 0) { + if (hp > sd->status.hp) + hp = sd->status.hp; + if (sp > sd->status.sp) + sp = sd->status.sp; + pc_heal(sd,-hp,-sp); } return 0; @@ -6838,10 +6288,10 @@ int pc_checkitem(struct map_session_data *sd) calc_flag = 1; } //?”õ§ŒÀƒ`ƒFƒbƒN - if(sd->status.inventory[i].equip && map[sd->bl.m].flag.pvp && (it->flag.no_equip==1 || it->flag.no_equip==3)){//PvP§ŒÀ + if(sd->status.inventory[i].equip && map[sd->bl.m].flag.pvp && (it->flag.no_equip&1)){//PVP check for forbiden items. optimized by [Lupus] sd->status.inventory[i].equip=0; calc_flag = 1; - }else if(sd->status.inventory[i].equip && map[sd->bl.m].flag.gvg && (it->flag.no_equip==2 || it->flag.no_equip==3)){//GvG§ŒÀ + }else if(sd->status.inventory[i].equip && map[sd->bl.m].flag.gvg && (it->flag.no_equip>1)){//GvG optimized by [Lupus] sd->status.inventory[i].equip=0; calc_flag = 1; } @@ -6849,7 +6299,7 @@ int pc_checkitem(struct map_session_data *sd) pc_setequipindex(sd); if(calc_flag) - pc_calcstatus(sd,2); + status_calc_pc(sd,2); return 0; } @@ -6912,7 +6362,7 @@ int pc_calc_pvprank(struct map_session_data *sd) nullpo_retr(0, sd); nullpo_retr(0, m=&map[sd->bl.m]); - + old=sd->pvp_rank; if( !(m->flag.pvp) ) @@ -6958,12 +6408,12 @@ int pc_ismarried(struct map_session_data *sd) return 0; } /*========================================== - * sd‚ªdstsd‚ÆŒ‹¥(dstsd¨sd‚ÌŒ‹¥?—‚à“¯Žž‚És‚¤) + * sd‚ªdstsd‚ÆŒ‹¥(dstsd¨sd‚ÌŒ‹¥?—‚à“¯ŽbÉs‚¤) *------------------------------------------ */ int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd) { - if(sd == NULL || dstsd == NULL || sd->status.partner_id > 0 || dstsd->status.partner_id > 0 || pc_calc_upper(sd->status.class)==2) + if(sd == NULL || dstsd == NULL || sd->status.partner_id > 0 || dstsd->status.partner_id > 0 || pc_calc_upper(sd->status.class_)==2) return -1; sd->status.partner_id=dstsd->status.char_id; dstsd->status.partner_id=sd->status.char_id; @@ -6971,7 +6421,7 @@ int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd) } /*========================================== - * sd‚ª—£¥(‘ŠŽè‚Ísd->status.partner_id‚Ɉ˂é)(‘ŠŽè‚à“¯Žž‚É—£¥?Œ‹¥Žw—ÖŽ©“®?’D) + * sd‚ª—£¥(‘ŠŽè‚Ísd->status.partner_id‚Ɉ˂é)(‘ŠŽè‚à“¯ŽbÉ—£¥?Œ‹¥Žw—ÖŽ©“®?’D) *------------------------------------------ */ int pc_divorce(struct map_session_data *sd) @@ -7003,25 +6453,78 @@ int pc_divorce(struct map_session_data *sd) } /*========================================== + * sd - father dstsd - mother jasd - child + */ +int pc_adoption(struct map_session_data *sd,struct map_session_data *dstsd, struct map_session_data *jasd) +{ + int j; + if(sd == NULL || dstsd == NULL || jasd == NULL || sd->status.partner_id <= 0 || dstsd->status.partner_id <= 0 || sd->status.partner_id != dstsd->status.char_id || dstsd->status.partner_id != sd->status.char_id || sd->status.child > 0 || dstsd->status.child || jasd->status.father > 0 || jasd->status.mother > 0) + return -1; + jasd->status.father=sd->status.char_id; + jasd->status.mother=dstsd->status.char_id; + sd->status.child=jasd->status.char_id; + dstsd->status.child=jasd->status.char_id; + for (j=0; j < MAX_INVENTORY; j++) { + if(jasd->status.inventory[j].nameid>0 && jasd->status.inventory[j].equip!=0) + pc_unequipitem(jasd, j, 3); + } + if (pc_jobchange(jasd, 4023, 0) == 0) + clif_displaymessage(jasd->fd, msg_table[12]); // Your job has been changed. + else { + clif_displaymessage(jasd->fd, msg_table[155]); // Impossible to change your job. + return -1; + } + return 0; +} + +/*========================================== * sd‚Ì‘Š•û‚Ìmap_session_data‚ð•Ô‚· *------------------------------------------ */ struct map_session_data *pc_get_partner(struct map_session_data *sd) { - struct map_session_data *p_sd = NULL; - char *nick; - if(sd == NULL || !pc_ismarried(sd)) - return NULL; + //struct map_session_data *p_sd = NULL; + //char *nick; + //if(sd == NULL || !pc_ismarried(sd)) + // return NULL; + //nick=map_charid2nick(sd->status.partner_id); + //if (nick==NULL) + // return NULL; + //if((p_sd=map_nick2sd(nick)) == NULL ) + // return NULL; - nick=map_charid2nick(sd->status.partner_id); + if (sd && pc_ismarried(sd)) + // charid2sd returns NULL if not found + return map_charid2sd(sd->status.partner_id); - if (nick==NULL) - return NULL; + return NULL; +} - if((p_sd=map_nick2sd(nick)) == NULL ) - return NULL; +struct map_session_data *pc_get_father (struct map_session_data *sd) +{ + if (sd && pc_calc_upper(sd->status.class_) == 2 && sd->status.father > 0) + // charid2sd returns NULL if not found + return map_charid2sd(sd->status.father); - return p_sd; + return NULL; +} + +struct map_session_data *pc_get_mother (struct map_session_data *sd) +{ + if (sd && pc_calc_upper(sd->status.class_) == 2 && sd->status.mother > 0) + // charid2sd returns NULL if not found + return map_charid2sd(sd->status.mother); + + return NULL; +} + +struct map_session_data *pc_get_child (struct map_session_data *sd) +{ + if (sd && pc_ismarried(sd) && sd->status.child > 0) + // charid2sd returns NULL if not found + return map_charid2sd(sd->status.child); + + return NULL; } // @@ -7054,8 +6557,8 @@ static int pc_spheal(struct map_session_data *sd) if(gc) { struct guild *g; g=guild_search(sd->status.guild_id); - if(g && g->guild_id == gc->guild_id) - a += a; + if(g && g->guild_id == gc->guild_id) + a += a; } // end addition [Valaris] return a; @@ -7084,8 +6587,8 @@ static int pc_hpheal(struct map_session_data *sd) if(gc) { struct guild *g; g=guild_search(sd->status.guild_id); - if(g && g->guild_id == gc->guild_id) - a += a; + if(g && g->guild_id == gc->guild_id) + a += a; } // end addition [Valaris] return a; @@ -7098,7 +6601,10 @@ static int pc_natural_heal_hp(struct map_session_data *sd) nullpo_retr(0, sd); - if (sd->sc_data[SC_TRICKDEAD].timer != -1) // Modified by RoVeRT + if (sd->sc_count && sd->sc_data[SC_TRICKDEAD].timer != -1) // Modified by RoVeRT + return 0; + + if (sd->no_regen & 1) return 0; if(pc_checkoverhp(sd)) { @@ -7111,11 +6617,11 @@ static int pc_natural_heal_hp(struct map_session_data *sd) if(sd->walktimer == -1) { inc_num = pc_hpheal(sd); - if( sd->sc_data[SC_TENSIONRELAX].timer!=-1 ){ // ƒeƒ“ƒVƒ‡ƒ“ƒŠƒ‰ƒbƒNƒX + if(sd->sc_data[SC_TENSIONRELAX].timer!=-1 ){ // ƒeƒ“ƒVƒ‡ƒ“ƒŠƒ‰ƒbƒNƒX sd->hp_sub += 2*inc_num; sd->inchealhptick += 3*natural_heal_diff_tick; - }else{ - sd->hp_sub += inc_num; + } else { + sd->hp_sub += inc_num; sd->inchealhptick += natural_heal_diff_tick; } } @@ -7168,7 +6674,7 @@ static int pc_natural_heal_hp(struct map_session_data *sd) return 0; - if(sd->sc_data[SC_APPLEIDUN].timer!=-1) { // Apple of Idun + if(sd->sc_count && sd->sc_data[SC_APPLEIDUN].timer!=-1 && sd->sc_data[SC_BERSERK].timer==-1) { // Apple of Idun if(sd->inchealhptick >= 6000 && sd->status.hp < sd->status.max_hp) { bonus = skill*20; while(sd->inchealhptick >= 6000) { @@ -7196,8 +6702,12 @@ static int pc_natural_heal_sp(struct map_session_data *sd) nullpo_retr(0, sd); - if (sd->sc_data[SC_TRICKDEAD].timer != -1 || // Modified by RoVeRT - sd->sc_data[SC_BERSERK].timer != -1) + if (sd->sc_count && (sd->sc_data[SC_TRICKDEAD].timer != -1 || // Modified by RoVeRT + sd->sc_data[SC_BERSERK].timer != -1 || + sd->sc_data[SC_BLEEDING].timer != -1)) + return 0; + + if (sd->no_regen & 2) return 0; if(pc_checkoversp(sd)) { @@ -7232,7 +6742,7 @@ static int pc_natural_heal_sp(struct map_session_data *sd) if(sd->nshealsp > 0) { if(sd->inchealsptick >= battle_config.natural_heal_skill_interval && sd->status.sp < sd->status.max_sp) { - struct pc_base_job s_class = pc_calc_base_job(sd->status.class); + struct pc_base_job s_class = pc_calc_base_job(sd->status.class_); if(sd->doridori_counter && s_class.job == 23) bonus = sd->nshealsp*2; else @@ -7256,7 +6766,7 @@ static int pc_natural_heal_sp(struct map_session_data *sd) return 0; } -static int pc_spirit_heal_hp(struct map_session_data *sd,int level) +static int pc_spirit_heal_hp(struct map_session_data *sd) { int bonus_hp,interval = battle_config.natural_heal_skill_interval; @@ -7296,7 +6806,7 @@ static int pc_spirit_heal_hp(struct map_session_data *sd,int level) return 0; } -static int pc_spirit_heal_sp(struct map_session_data *sd,int level) +static int pc_spirit_heal_sp(struct map_session_data *sd) { int bonus_sp,interval = battle_config.natural_heal_skill_interval; @@ -7337,6 +6847,30 @@ static int pc_spirit_heal_sp(struct map_session_data *sd,int level) return 0; } +static int pc_bleeding (struct map_session_data *sd) +{ + int interval, hp; + + nullpo_retr(0, sd); + interval = sd->hp_loss_rate; + hp = sd->hp_loss_value; + + sd->hp_loss_tick += natural_heal_diff_tick; + if(sd->hp_loss_tick >= interval) { + while(sd->hp_loss_tick >= interval) { + sd->hp_loss_tick -= interval; + if (sd->status.hp < hp) + hp = sd->status.hp; + if (sd->hp_loss_type == 1) { + clif_damage(&sd->bl,&sd->bl,gettick(),0,0,hp,0,0,0); + } + pc_heal(sd,-hp,0); + sd->hp_loss_tick = 0; + } + } + return 0; +} + /*========================================== * HP/SP Ž©‘R‰ñ•œ ŠeƒNƒ‰ƒCƒAƒ“ƒg *------------------------------------------ @@ -7344,33 +6878,43 @@ static int pc_spirit_heal_sp(struct map_session_data *sd,int level) static int pc_natural_heal_sub(struct map_session_data *sd,va_list ap) { int skill; + int tick; nullpo_retr(0, sd); + tick = va_arg(ap,int); // -- moonsoul (if conditions below altered to disallow natural healing if under berserk status) if ((battle_config.natural_heal_weight_rate > 100 || sd->weight*100/sd->max_weight < battle_config.natural_heal_weight_rate) && - !pc_isdead(sd) && - !pc_ishiding(sd) && - !(sd->sc_data[SC_POISON].timer != -1 && sd->sc_data[SC_SLOWPOISON].timer == -1) && - sd->sc_data[SC_BERSERK].timer == -1 ) { + !pc_isdead(sd) && + !pc_ishiding(sd) && + //-- cannot regen for 5 minutes after using Berserk --- [Celest] + DIFF_TICK (tick, sd->canregen_tick)>=0 && + (sd->sc_data && !(sd->sc_data[SC_POISON].timer != -1 && sd->sc_data[SC_SLOWPOISON].timer == -1) && + sd->sc_data[SC_BERSERK].timer == -1 )) { pc_natural_heal_hp(sd); if( sd->sc_data && sd->sc_data[SC_EXTREMITYFIST].timer == -1 && //ˆ¢C—…?‘Ô‚Å‚ÍSP‚ª‰ñ•œ‚µ‚È‚¢ sd->sc_data[SC_DANCING].timer == -1 && //ƒ_ƒ“ƒX?‘Ô‚Å‚ÍSP‚ª‰ñ•œ‚µ‚È‚¢ sd->sc_data[SC_BERSERK].timer == -1 ) //ƒo?ƒT?ƒN?‘Ô‚Å‚ÍSP‚ª‰ñ•œ‚µ‚È‚¢ pc_natural_heal_sp(sd); + sd->canregen_tick = tick; } else { sd->hp_sub = sd->inchealhptick = 0; sd->sp_sub = sd->inchealsptick = 0; } if((skill = pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0 && !pc_ishiding(sd) && sd->sc_data[SC_POISON].timer == -1 && sd->sc_data[SC_BERSERK].timer == -1){ - pc_spirit_heal_hp(sd,skill); - pc_spirit_heal_sp(sd,skill); + pc_spirit_heal_hp(sd); + pc_spirit_heal_sp(sd); } else { sd->inchealspirithptick = 0; sd->inchealspiritsptick = 0; } + if (sd->hp_loss_value > 0) + pc_bleeding(sd); + else + sd->hp_loss_tick = 0; + return 0; } @@ -7382,7 +6926,7 @@ int pc_natural_heal(int tid,unsigned int tick,int id,int data) { natural_heal_tick = tick; natural_heal_diff_tick = DIFF_TICK(natural_heal_tick,natural_heal_prev_tick); - clif_foreachclient(pc_natural_heal_sub); + clif_foreachclient(pc_natural_heal_sub, tick); natural_heal_prev_tick = tick; return 0; @@ -7412,9 +6956,10 @@ static int pc_autosave_sub(struct map_session_data *sd,va_list ap) { nullpo_retr(0, sd); - if(save_flag==0 && sd->fd>last_save_fd){ - struct guild_castle *gc=NULL; - int i; + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + + if(save_flag==0 && sd->fd>last_save_fd && !sd->state.waitingdisconnect){ + // if(battle_config.save_log) // printf("autosave %d\n",sd->fd); // pet @@ -7424,19 +6969,6 @@ static int pc_autosave_sub(struct map_session_data *sd,va_list ap) chrif_save(sd); storage_storage_save(sd); - for(i=0;i<MAX_GUILDCASTLE;i++){ - gc=guild_castle_search(i); - if(!gc) continue; - if(gc->visibleG0==1) guild_castledatasave(gc->castle_id,18,gc->Ghp0); - if(gc->visibleG1==1) guild_castledatasave(gc->castle_id,19,gc->Ghp1); - if(gc->visibleG2==1) guild_castledatasave(gc->castle_id,20,gc->Ghp2); - if(gc->visibleG3==1) guild_castledatasave(gc->castle_id,21,gc->Ghp3); - if(gc->visibleG4==1) guild_castledatasave(gc->castle_id,22,gc->Ghp4); - if(gc->visibleG5==1) guild_castledatasave(gc->castle_id,23,gc->Ghp5); - if(gc->visibleG6==1) guild_castledatasave(gc->castle_id,24,gc->Ghp6); - if(gc->visibleG7==1) guild_castledatasave(gc->castle_id,25,gc->Ghp7); - } - save_flag=1; last_save_fd = sd->fd; } @@ -7471,10 +7003,10 @@ int pc_read_gm_account(int fd) int i = 0; #endif if (gm_account != NULL) - free(gm_account); + aFree(gm_account); GM_num = 0; #ifdef TXT_ONLY - gm_account = calloc(sizeof(struct gm_account) * ((RFIFOW(fd,2) - 4) / 5), 1); + gm_account = (struct gm_account *) aCallocA(sizeof(struct gm_account) * ((RFIFOW(fd,2) - 4) / 5), 1); for (i = 4; i < RFIFOW(fd,2); i = i + 5) { gm_account[GM_num].account_id = RFIFOL(fd,i); gm_account[GM_num].level = (int)RFIFOB(fd,i+4); @@ -7488,7 +7020,7 @@ int pc_read_gm_account(int fd) } lsql_res = mysql_store_result(&lmysql_handle); if (lsql_res) { - gm_account = calloc(sizeof(struct gm_account) * mysql_num_rows(lsql_res), 1); + gm_account = (struct gm_account *) aCallocA(sizeof(struct gm_account) * mysql_num_rows(lsql_res), 1); while ((lsql_row = mysql_fetch_row(lsql_res))) { gm_account[GM_num].account_id = atoi(lsql_row[0]); gm_account[GM_num].level = atoi(lsql_row[1]); @@ -7496,7 +7028,7 @@ int pc_read_gm_account(int fd) GM_num++; } } - + mysql_free_result(lsql_res); #endif /* TXT_ONLY */ return GM_num; @@ -7516,9 +7048,13 @@ int map_day_timer(int tid, unsigned int tick, int id, int data) { // by [yor] strcpy(tmpstr, msg_txt(502)); // The day has arrived! night_flag = 0; // 0=day, 1=night [Yor] for(i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) { - pl_sd->opt2 &= ~STATE_BLIND; - clif_changeoption(&pl_sd->bl); + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) { + if (battle_config.night_darkness_level > 0) + clif_refresh (pl_sd); + else { + pl_sd->opt2 &= ~STATE_BLIND; + clif_changeoption(&pl_sd->bl); + } clif_wis_message(pl_sd->fd, wisp_server_name, tmpstr, strlen(tmpstr)+1); } } @@ -7542,7 +7078,7 @@ int map_night_timer(int tid, unsigned int tick, int id, int data) { // by [yor] strcpy(tmpstr, msg_txt(503)); // The night has fallen... night_flag = 1; // 0=day, 1=night [Yor] for(i = 0; i < fd_max; i++) { - if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && !map[pl_sd->bl.m].flag.indoors) { + if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && !map[pl_sd->bl.m].flag.indoors) { if (battle_config.night_darkness_level > 0) clif_specialeffect(&pl_sd->bl, 474 + battle_config.night_darkness_level, 0); else { @@ -7562,8 +7098,8 @@ int map_night_timer(int tid, unsigned int tick, int id, int data) { // by [yor] void pc_setstand(struct map_session_data *sd){ nullpo_retv(sd); - if(sd->sc_data && sd->sc_data[SC_TENSIONRELAX].timer!=-1) - skill_status_change_end(&sd->bl,SC_TENSIONRELAX,-1); + if(sd->sc_count && sd->sc_data[SC_TENSIONRELAX].timer!=-1) + status_change_end(&sd->bl,SC_TENSIONRELAX,-1); sd->state.dead_sit = 0; } @@ -7590,7 +7126,7 @@ int pc_readdb(void) char line[1024],*p; // •K—v??’l?‚Ý?‚Ý - + memset(exp_table,0,sizeof(exp_table)); fp=fopen("db/exp.txt","r"); if(fp==NULL){ printf("can't read db/exp.txt\n"); @@ -7622,93 +7158,8 @@ int pc_readdb(void) break; } fclose(fp); - printf("read db/exp.txt done\n"); - - // JOB•â³?’l‚P - fp=fopen("db/job_db1.txt","r"); - if(fp==NULL){ - printf("can't read db/job_db1.txt\n"); - return 1; - } - i=0; - while(fgets(line, sizeof(line)-1, fp)){ - char *split[50]; - if(line[0]=='/' && line[1]=='/') - continue; - for(j=0,p=line;j<21 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - if(j<21) - continue; - max_weight_base[i]=atoi(split[0]); - hp_coefficient[i]=atoi(split[1]); - hp_coefficient2[i]=atoi(split[2]); - sp_coefficient[i]=atoi(split[3]); - for(j=0;j<17;j++) - aspd_base[i][j]=atoi(split[j+4]); - i++; -// -- moonsoul (below two lines added to accommodate high numbered new class ids) - if(i==24) - i=4001; - if(i==MAX_PC_CLASS) - break; - } - fclose(fp); - printf("read db/job_db1.txt done\n"); - - // JOBƒ{?ƒiƒX - fp=fopen("db/job_db2.txt","r"); - if(fp==NULL){ - printf("can't read db/job_db2.txt\n"); - return 1; - } - i=0; - while(fgets(line, sizeof(line)-1, fp)){ - if(line[0]=='/' && line[1]=='/') - continue; - for(j=0,p=line;j<MAX_LEVEL && p;j++){ - if(sscanf(p,"%d",&k)==0) - break; - job_bonus[0][i][j]=k; - job_bonus[2][i][j]=k; //—{ŽqE‚̃{?ƒiƒX‚Í•ª‚©‚ç‚È‚¢‚Ì‚Å? - p=strchr(p,','); - if(p) p++; - } - i++; -// -- moonsoul (below two lines added to accommodate high numbered new class ids) - if(i==24) - i=4001; - if(i==MAX_PC_CLASS) - break; - } - fclose(fp); - printf("read db/job_db2.txt done\n"); - - // JOBƒ{?ƒiƒX2 ?¶E—p - fp=fopen("db/job_db2-2.txt","r"); - if(fp==NULL){ - printf("can't read db/job_db2-2.txt\n"); - return 1; - } - i=0; - while(fgets(line, sizeof(line)-1, fp)){ - if(line[0]=='/' && line[1]=='/') - continue; - for(j=0,p=line;j<MAX_LEVEL && p;j++){ - if(sscanf(p,"%d",&k)==0) - break; - job_bonus[1][i][j]=k; - p=strchr(p,','); - if(p) p++; - } - i++; - if(i==MAX_PC_CLASS) - break; - } - fclose(fp); - printf("read db/job_db2-2.txt done\n"); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/exp.txt"); + ShowStatus(tmp_output); // ƒXƒLƒ‹ƒcƒŠ? memset(skill_tree,0,sizeof(skill_tree)); @@ -7720,36 +7171,41 @@ int pc_readdb(void) while(fgets(line, sizeof(line)-1, fp)){ char *split[50]; + int f=0, m=3; if(line[0]=='/' && line[1]=='/') continue; - for(j=0,p=line;j<13 && p;j++){ + for(j=0,p=line;j<14 && p;j++){ split[j]=p; p=strchr(p,','); if(p) *p++=0; } if(j<13) continue; - //i=atoi(split[0]); + if (j == 14) { + f=1; // MinJobLvl has been added + m++; + } s_class = pc_calc_base_job(atoi(split[0])); i = s_class.job; u = s_class.upper; - for(j=0;skill_tree[u][i][j].id;j++); + // check for bounds [celest] + if (i > 25 || u > 3) + continue; + for(j = 0; skill_tree[u][i][j].id && j < MAX_SKILL_TREE; j++); + if (j == MAX_SKILL_TREE) + continue; skill_tree[u][i][j].id=atoi(split[1]); skill_tree[u][i][j].max=atoi(split[2]); - - //not required - Celest - //skill_tree[2][i][j].id=atoi(split[1]); //—{ŽqE‚Í—Ç‚•ª‚©‚ç‚È‚¢‚̂Ŏb’è - //skill_tree[2][i][j].max=atoi(split[2]); //—{ŽqE‚Í—Ç‚•ª‚©‚ç‚È‚¢‚̂Ŏb’è + if (f) skill_tree[u][i][j].joblv=atoi(split[3]); for(k=0;k<5;k++){ - skill_tree[u][i][j].need[k].id=atoi(split[k*2+3]); - skill_tree[u][i][j].need[k].lv=atoi(split[k*2+4]); - //skill_tree[2][i][j].need[k].id=atoi(split[k*2+3]); //—{ŽqE‚Í—Ç‚•ª‚©‚ç‚È‚¢‚̂Ŏb’è - //skill_tree[2][i][j].need[k].lv=atoi(split[k*2+4]); //—{ŽqE‚Í—Ç‚•ª‚©‚ç‚È‚¢‚̂Ŏb’è + skill_tree[u][i][j].need[k].id=atoi(split[k*2+m]); + skill_tree[u][i][j].need[k].lv=atoi(split[k*2+m+1]); } } fclose(fp); - printf("read db/skill_tree.txt done\n"); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_tree.txt"); + ShowStatus(tmp_output); // ?«C³ƒe?ƒuƒ‹ for(i=0;i<4;i++) @@ -7795,135 +7251,52 @@ int pc_readdb(void) } } fclose(fp); - printf("read db/attr_fix.txt done\n"); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/attr_fix.txt"); + ShowStatus(tmp_output); - // ƒTƒCƒY•ⳃe?ƒuƒ‹ - for(i=0;i<3;i++) - for(j=0;j<20;j++) - atkmods[i][j]=100; - fp=fopen("db/size_fix.txt","r"); - if(fp==NULL){ - printf("can't read db/size_fix.txt\n"); - return 1; - } - i=0; - while(fgets(line, sizeof(line)-1, fp)){ - char *split[20]; - if(line[0]=='/' && line[1]=='/') - continue; - if(atoi(line)<=0) - continue; - memset(split,0,sizeof(split)); - for(j=0,p=line;j<20 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; + // ƒXƒLƒ‹ƒcƒŠ? + memset(statp,0,sizeof(statp)); + i=1; + j=45; // base points + fp=fopen("db/statpoint.txt","r"); + if(fp == NULL){ + sprintf(tmp_output,"Can't read '"CL_WHITE"%s"CL_RESET"'... Generating DB.\n","db/statpoint.txt"); + //return 1; + } else { + while(fgets(line, sizeof(line)-1, fp)){ + if(line[0]=='/' && line[1]=='/') + continue; + if ((j=atoi(line))<0) + j=0; + if (i >= MAX_LEVEL) + break; + statp[i]=j; + i++; } - for(j=0;j<20 && split[j];j++) - atkmods[i][j]=atoi(split[j]); - i++; - } - fclose(fp); - printf("read db/size_fix.txt done\n"); - - // ¸?ƒf?ƒ^ƒe?ƒuƒ‹ - for(i=0;i<5;i++){ - for(j=0;j<10;j++) - percentrefinery[i][j]=100; - refinebonus[i][0]=0; - refinebonus[i][1]=0; - refinebonus[i][2]=10; - } - fp=fopen("db/refine_db.txt","r"); - if(fp==NULL){ - printf("can't read db/refine_db.txt\n"); - return 1; + fclose(fp); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/statpoint.txt"); } - i=0; - while(fgets(line, sizeof(line)-1, fp)){ - char *split[16]; - if(line[0]=='/' && line[1]=='/') - continue; - if(atoi(line)<=0) - continue; - memset(split,0,sizeof(split)); - for(j=0,p=line;j<16 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - refinebonus[i][0]=atoi(split[0]); // ¸?ƒ{?ƒiƒX - refinebonus[i][1]=atoi(split[1]); // ‰ß?¸?ƒ{?ƒiƒX - refinebonus[i][2]=atoi(split[2]); // ˆÀ‘S¸?ŒÀŠE - for(j=0;j<10 && split[j];j++) - percentrefinery[i][j]=atoi(split[j+3]); - i++; + // generate the remaining parts of the db if necessary + for (; i < MAX_LEVEL; i++) { + j += (i+15)/5; + statp[i] = j; } - fclose(fp); //Lupus. close this file!!! - printf("read db/refine_db.txt done\n"); - - return 0; -} - -static int pc_calc_sigma(void) -{ - int i,j,k; + ShowStatus(tmp_output); - for(i=0;i<MAX_PC_CLASS;i++) { - memset(hp_sigma_val[i],0,sizeof(hp_sigma_val[i])); - for(k=0,j=2;j<=MAX_LEVEL;j++) { - k += hp_coefficient[i]*j + 50; - k -= k%100; - hp_sigma_val[i][j-1] = k; - } - } return 0; } -static void pc_statpointdb(void) -{ - char * buf_stat; - int i=0,j=0,k=0,l=0, end = 0; - - FILE *stp; - - stp=fopen("db/statpoint.txt","r"); - - if(stp==NULL){ - printf("can't read db/statpoint.txt\n"); - return; - } - - fseek(stp, 0, SEEK_END); - end = ftell(stp); - rewind(stp); - - buf_stat = (char *) malloc (end + 1); - l = fread(buf_stat,1,end,stp); - fclose(stp); - printf("read db/statpoint.txt done (size=%d)\n",l); - - for(i=0;i<255;i++) { - j=0; - while (*(buf_stat+k)!='\n') { - statp[i][j]=*(buf_stat+k); - j++;k++; - } - statp[i][j+1]='\0'; - k++; - } - - free(buf_stat); -} - /*========================================== * pc? ŒW‰Šú‰» *------------------------------------------ */ +void do_final_pc(void) { + if (gm_account) + aFree(gm_account); + return; +} int do_init_pc(void) { pc_readdb(); - pc_statpointdb(); - pc_calc_sigma(); // gm_account_db = numdb_init(); @@ -7942,16 +7315,13 @@ int do_init_pc(void) { pc_read_gm_account(0); #endif /* not TXT_ONLY */ - // add night/day timer (by [yor]) - add_timer_func_list(map_day_timer, "map_day_timer"); // by [yor] - add_timer_func_list(map_night_timer, "map_night_timer"); // by [yor] - { + if (battle_config.day_duration > 0 && battle_config.night_duration > 0) { int day_duration = battle_config.day_duration; int night_duration = battle_config.night_duration; - if (day_duration < 60000) - day_duration = 60000; - if (night_duration < 60000) - night_duration = 60000; + // add night/day timer (by [yor]) + add_timer_func_list(map_day_timer, "map_day_timer"); // by [yor] + add_timer_func_list(map_night_timer, "map_night_timer"); // by [yor] + if (battle_config.night_at_start == 0) { night_flag = 0; // 0=day, 1=night [Yor] day_timer_tid = add_timer_interval(gettick() + day_duration + night_duration, map_day_timer, 0, 0, day_duration + night_duration); diff --git a/src/map/pc.h b/src/map/pc.h index 372dd72f7..6aec36d38 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -7,6 +7,9 @@ #define OPTION_MASK 0xd7b8 #define CART_MASK 0x788 +#define STATE_BLIND 0x10 + +#define MAX_SKILL_TREE 51 #define pc_setdead(sd) ((sd)->state.dead_sit = 1) #define pc_setsit(sd) ((sd)->state.dead_sit = 2) @@ -37,14 +40,19 @@ int pc_authfail(int); int pc_isequip(struct map_session_data *sd,int n); int pc_equippoint(struct map_session_data *sd,int n); -int pc_breakweapon(struct map_session_data *sd); // weapon breaking [Valaris] -int pc_breakarmor(struct map_session_data *sd); // armor breaking [Valaris] +int pc_break_equip(struct map_session_data *, unsigned short); +#define pc_breakweapon(sd) (pc_break_equip(sd, EQP_WEAPON)) +#define pc_breakarmor(sd) (pc_break_equip(sd, EQP_ARMOR)) +#define pc_breakshield(sd) (pc_break_equip(sd, EQP_SHIELD)) +#define pc_breakhelm(sd) (pc_break_equip(sd, EQP_HELM)) int pc_checkskill(struct map_session_data *sd,int skill_id); int pc_checkallowskill(struct map_session_data *sd); int pc_checkequip(struct map_session_data *sd,int pos); +int pc_calc_skilltree(struct map_session_data *sd); int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd); +int pc_clean_skilltree(struct map_session_data *sd); int pc_checkoverhp(struct map_session_data*); int pc_checkoversp(struct map_session_data*); @@ -57,6 +65,8 @@ int pc_setpos(struct map_session_data*,char*,int,int,int); int pc_setsavepoint(struct map_session_data*,char*,int,int); int pc_randomwarp(struct map_session_data *sd,int type); int pc_memo(struct map_session_data *sd,int i); +int pc_randomwalk(struct map_session_data*,int tick); +int pc_remove_map(struct map_session_data *sd,int clrtype); int pc_checkadditem(struct map_session_data*,int,int); int pc_inventoryblank(struct map_session_data*); @@ -78,13 +88,14 @@ int pc_dropitem(struct map_session_data*,int,int); int pc_checkweighticon(struct map_session_data *sd); -int pc_calcstatus(struct map_session_data*,int); -int pc_calcspeed(struct map_session_data*); // [Celest] int pc_bonus(struct map_session_data*,int,int); int pc_bonus2(struct map_session_data *sd,int,int,int); int pc_bonus3(struct map_session_data *sd,int,int,int,int); +int pc_bonus4(struct map_session_data *sd,int,int,int,int,int); int pc_skill(struct map_session_data*,int,int,int); +int pc_blockskill_start (struct map_session_data*,int,int); // [celest] + int pc_insert_card(struct map_session_data *sd,int idx_card,int idx_equip); int pc_item_identify(struct map_session_data *sd,int idx); @@ -117,7 +128,7 @@ int pc_resetlvl(struct map_session_data*,int type); int pc_resetstate(struct map_session_data*); int pc_resetskill(struct map_session_data*); int pc_equipitem(struct map_session_data*,int,int); -int pc_unequipitem(struct map_session_data*,int,int,int); +int pc_unequipitem(struct map_session_data*,int,int); int pc_checkitem(struct map_session_data*); int pc_useitem(struct map_session_data*,int); @@ -145,7 +156,6 @@ int pc_readaccountreg(struct map_session_data*,char*); int pc_setaccountreg(struct map_session_data*,char*,int); int pc_readaccountreg2(struct map_session_data*,char*); int pc_setaccountreg2(struct map_session_data*,char*,int); -int pc_percentrefinery(struct map_session_data *sd,struct item *item); int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name); int pc_deleventtimer(struct map_session_data *sd,const char *name); @@ -158,10 +168,16 @@ int pc_calc_pvprank_timer(int tid,unsigned int tick,int id,int data); int pc_ismarried(struct map_session_data *sd); int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd); int pc_divorce(struct map_session_data *sd); +int pc_adoption(struct map_session_data *sd,struct map_session_data *dstsd,struct map_session_data *jasd); struct map_session_data *pc_get_partner(struct map_session_data *sd); +struct map_session_data *pc_get_father(struct map_session_data *sd); +struct map_session_data *pc_get_mother(struct map_session_data *sd); +struct map_session_data *pc_get_child(struct map_session_data *sd); + int pc_set_gm_level(int account_id, int level); void pc_setstand(struct map_session_data *sd); - +int pc_break_equip(struct map_session_data *sd, unsigned short where); +int pc_candrop(struct map_session_data *sd,int item_id); struct pc_base_job{ int job; //E‹ÆA‚½‚¾‚µ“]¶E‚â—{ŽqE‚Ìꇂ͌³‚ÌE‹Æ‚ð•Ô‚·(”pƒvƒŠ¨ƒvƒŠ) @@ -174,12 +190,15 @@ int pc_calc_base_job2(int b_class); // Celest int pc_calc_upper(int b_class); struct skill_tree_entry { - int id; - int max; + short id; + unsigned char max; + unsigned char joblv; struct { - short id,lv; - } need[6]; -} skill_tree[3][MAX_PC_CLASS][100]; // Celest + short id; + unsigned char lv; + } need[5]; +}; // Celest +extern struct skill_tree_entry skill_tree[3][25][MAX_SKILL_TREE]; int pc_read_gm_account(int fd); int pc_setinvincibletimer(struct map_session_data *sd,int); @@ -187,13 +206,17 @@ int pc_delinvincibletimer(struct map_session_data *sd); int pc_addspiritball(struct map_session_data *sd,int,int); int pc_delspiritball(struct map_session_data *sd,int,int); +int pc_eventtimer(int tid,unsigned int tick,int id,int data); // for npc_dequeue + +int pc_readdb(void); int do_init_pc(void); +void do_final_pc(void); enum {ADDITEM_EXIST,ADDITEM_NEW,ADDITEM_OVERAMOUNT}; // timer for night.day -int day_timer_tid; -int night_timer_tid; +extern int day_timer_tid; +extern int night_timer_tid; int map_day_timer(int,unsigned int,int,int); // by [yor] int map_night_timer(int,unsigned int,int,int); // by [yor] diff --git a/src/map/pet.c b/src/map/pet.c index 6026b1ebf..6f4713d75 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -9,6 +9,7 @@ #include "nullpo.h" #include "malloc.h" #include "pc.h" +#include "status.h" #include "map.h" #include "intif.h" #include "clif.h" @@ -20,6 +21,7 @@ #include "npc.h" #include "script.h" #include "skill.h" +#include "showmsg.h" #ifdef MEMWATCH #include "memwatch.h" @@ -48,6 +50,8 @@ static int calc_next_walk_step(struct pet_data *pd) { nullpo_retr(0, pd); + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + if(pd->walkpath.path_pos>=pd->walkpath.path_len) return -1; if(pd->walkpath.path[pd->walkpath.path_pos]&1) @@ -59,6 +63,8 @@ static int pet_performance_val(struct map_session_data *sd) { nullpo_retr(0, sd); + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + if(sd->pet.intimate > 900) return (sd->petDB->s_perfor > 0)? 4:3; else if(sd->pet.intimate > 750) @@ -71,6 +77,8 @@ int pet_hungry_val(struct map_session_data *sd) { nullpo_retr(0, sd); + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + if(sd->pet.hungry > 90) return 4; else if(sd->pet.hungry > 75) @@ -89,6 +97,8 @@ static int pet_can_reach(struct pet_data *pd,int x,int y) nullpo_retr(0, pd); + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + if( pd->bl.x==x && pd->bl.y==y ) // “¯‚¶ƒ}ƒX return 1; @@ -106,6 +116,8 @@ static int pet_calc_pos(struct pet_data *pd,int tx,int ty,int dir) nullpo_retr(0, pd); + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + pd->to_x = tx; pd->to_y = ty; @@ -161,23 +173,27 @@ static int pet_attack(struct pet_data *pd,unsigned int tick,int data) nullpo_retr(0, pd); + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + pd->state.state=MS_IDLE; md=(struct mob_data *)map_id2bl(pd->target_id); if(md == NULL || md->bl.type != BL_MOB || pd->bl.m != md->bl.m || md->bl.prev == NULL || - distance(pd->bl.x,pd->bl.y,md->bl.x,md->bl.y) > 13) { + distance(pd->bl.x,pd->bl.y,md->bl.x,md->bl.y) > 13 || + (!agit_flag && md->class_ >= 1285 && md->class_ <= 1288)) // Cannot attack Guardians outside of WoE + { pd->target_id=0; return 0; } - mode=mob_db[pd->class].mode; - race=mob_db[pd->class].race; - if(mob_db[pd->class].mexp <= 0 && !(mode&0x20) && (md->option & 0x06 && race != 4 && race != 6) ) { + mode=mob_db[pd->class_].mode; + race=mob_db[pd->class_].race; + if(mob_db[pd->class_].mexp <= 0 && !(mode&0x20) && (md->option & 0x06 && race != 4 && race != 6) ) { pd->target_id=0; return 0; } - range = mob_db[pd->class].range + 1; + range = mob_db[pd->class_].range + 1; if(distance(pd->bl.x,pd->bl.y,md->bl.x,md->bl.y) > range) return 0; if(battle_config.monster_attack_direction_change) @@ -187,7 +203,7 @@ static int pet_attack(struct pet_data *pd,unsigned int tick,int data) pd->target_lv = battle_weapon_attack(&pd->bl,&md->bl,tick,0); - pd->attackabletime = tick + battle_get_adelay(&pd->bl); + pd->attackabletime = tick + status_get_adelay(&pd->bl); pd->timer=add_timer(pd->attackabletime,pet_timer,pd->bl.id,0); pd->state.state=MS_ATTACK; @@ -202,11 +218,13 @@ static int pet_attack(struct pet_data *pd,unsigned int tick,int data) static int pet_walk(struct pet_data *pd,unsigned int tick,int data) { int moveblock; - int i,ctype; + int i; int x,y,dx,dy; nullpo_retr(0, pd); + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + pd->state.state=MS_IDLE; if(pd->walkpath.path_pos >= pd->walkpath.path_len || pd->walkpath.path_pos != data) return 0; @@ -234,8 +252,7 @@ static int pet_walk(struct pet_data *pd,unsigned int tick,int data) dx = dirx[pd->dir]; dy = diry[pd->dir]; - ctype = map_getcell(pd->bl.m,x+dx,y+dy); - if(ctype == 1 || ctype == 5) { + if(map_getcell(pd->bl.m,x+dx,y+dy,CELL_CHKNOPASS)){ pet_walktoxy_sub(pd); return 0; } @@ -273,6 +290,8 @@ int pet_stopattack(struct pet_data *pd) { nullpo_retr(0, pd); + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + pd->target_id=0; if(pd->state.state == MS_ATTACK) pet_changestate(pd,MS_IDLE,0); @@ -290,15 +309,17 @@ int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type) pd = sd->pd; - if(bl && pd && bl->type == BL_MOB && sd->pet.intimate > 900 && sd->pet.hungry > 0 && pd->class != battle_get_class(bl) + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + + if(bl && pd && bl->type == BL_MOB && sd->pet.intimate > 900 && sd->pet.hungry > 0 && pd->class_ != status_get_class(bl) && pd->state.state != MS_DELAY) { - mode=mob_db[pd->class].mode; - race=mob_db[pd->class].race; + mode=mob_db[pd->class_].mode; + race=mob_db[pd->class_].race; md=(struct mob_data *)bl; if(md->bl.type != BL_MOB || pd->bl.m != md->bl.m || md->bl.prev == NULL || distance(pd->bl.x,pd->bl.y,md->bl.x,md->bl.y) > 13) return 0; - if(mob_db[pd->class].mexp <= 0 && !(mode&0x20) && (md->option & 0x06 && race!=4 && race!=6) ) + if(mob_db[pd->class_].mexp <= 0 && !(mode&0x20) && (md->option & 0x06 && race!=4 && race!=6) ) return 0; if(!type) { rate = sd->petDB->attack_rate; @@ -331,6 +352,8 @@ int pet_changestate(struct pet_data *pd,int state,int type) nullpo_retr(0, pd); + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + if(pd->timer != -1) delete_timer(pd->timer,pet_timer); pd->timer=-1; @@ -368,6 +391,8 @@ static int pet_timer(int tid,unsigned int tick,int id,int data) if(pd == NULL || pd->bl.type != BL_PET) return 1; + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + if(pd->timer != tid){ if(battle_config.error_log) printf("pet_timer %d != %d\n",pd->timer,tid); @@ -403,6 +428,8 @@ static int pet_walktoxy_sub(struct pet_data *pd) nullpo_retr(0, pd); + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + if(path_search(&wpd,pd->bl.m,pd->bl.x,pd->bl.y,pd->to_x,pd->to_y,0)) return 1; memcpy(&pd->walkpath,&wpd,sizeof(wpd)); @@ -422,6 +449,8 @@ int pet_walktoxy(struct pet_data *pd,int x,int y) nullpo_retr(0, pd); + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + if(pd->state.state == MS_WALK && path_search(&wpd,pd->bl.m,pd->bl.x,pd->bl.y,x,y,0)) return 1; @@ -441,6 +470,8 @@ int pet_stop_walking(struct pet_data *pd,int type) { nullpo_retr(0, pd); + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + if(pd->state.state == MS_WALK || pd->state.state == MS_IDLE) { pd->walkpath.path_len=0; pd->to_x=pd->bl.x; @@ -461,10 +492,13 @@ static int pet_hungry(int tid,unsigned int tick,int id,int data) struct map_session_data *sd; int interval,t; + sd=map_id2sd(id); if(sd==NULL) return 1; + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + if(sd->pet_hungry_timer != tid){ if(battle_config.error_log) printf("pet_hungry_timer %d != %d\n",sd->pet_hungry_timer,tid); @@ -485,9 +519,9 @@ static int pet_hungry(int tid,unsigned int tick,int id,int data) sd->pet.intimate = 0; if(battle_config.pet_status_support && t > 0) { if(sd->bl.prev != NULL) - pc_calcstatus(sd,0); + status_calc_pc(sd,0); else - pc_calcstatus(sd,2); + status_calc_pc(sd,2); } } clif_send_petdata(sd,1,sd->pet.intimate); @@ -510,11 +544,11 @@ int search_petDB_index(int key,int type) int i; for(i=0;i<MAX_PET_DB;i++) { - if(pet_db[i].class <= 0) + if(pet_db[i].class_ <= 0) continue; switch(type) { case PET_CLASS: - if(pet_db[i].class == key) + if(pet_db[i].class_ == key) return i; break; case PET_CATCH: @@ -556,26 +590,29 @@ int pet_remove_map(struct map_session_data *sd) { nullpo_retr(0, sd); + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + if(sd->status.pet_id && sd->pd) { struct pet_data *pd=sd->pd; // [Valaris] if(pd->skillbonustimer!=-1) pd->skillbonustimer=-1; - if(pd->skillbonusduration!=-1) pd->skillbonusduration=-1; - if(pd->skilltype !=-1) pd->skilltype=-1; - if(pd->skillval !=-1) pd->skillval=-1; + pd->skilltype=0; + pd->skillval=0; if(pd->skilltimer!=-1) pd->skilltimer=-1; - if(pd->skillduration!=-1) pd->skillduration=-1; - if(pd->skillbonustype!=-1) pd->skillbonustype=-1; - if(pd->skillbonusval!=-1) pd->skillbonusval=-1; - if(sd->perfect_hiding==1) sd->perfect_hiding=0; // end additions + pd->state.skillbonus=-1; + pd->skillduration=0; + pd->skillbonustype=0; + pd->skillbonusval=0; + if(sd->perfect_hiding==1) sd->perfect_hiding=0; // end additions pet_changestate(sd->pd,MS_IDLE,0); if(sd->pet_hungry_timer != -1) pet_hungry_timer_delete(sd); clif_clearchar_area(&sd->pd->bl,0); map_delblock(&sd->pd->bl); + if (sd->pd->lootitem) + aFree(sd->pd->lootitem); map_deliddb(&sd->pd->bl); - map_freeblock(sd->pd); } return 0; } @@ -598,6 +635,8 @@ int pet_performance(struct map_session_data *sd) nullpo_retr(0, sd); nullpo_retr(0, pd=sd->pd); + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + pet_stop_walking(pd,2000<<8); clif_pet_performance(&pd->bl,rand()%pet_performance_val(sd) + 1); // ƒ‹[ƒg‚µ‚½Item‚𗎂Ƃ³‚¹‚é @@ -613,8 +652,11 @@ int pet_return_egg(struct map_session_data *sd) nullpo_retr(0, sd); + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + if(sd->status.pet_id && sd->pd) { - struct pet_data *pd=sd->pd; + // ƒ‹[ƒg‚µ‚½Item‚𗎂Ƃ³‚¹‚é + pet_lootitem_drop(sd->pd,sd); pet_remove_map(sd); sd->status.pet_id = 0; sd->pd = NULL; @@ -634,12 +676,10 @@ int pet_return_egg(struct map_session_data *sd) } if(battle_config.pet_status_support && sd->pet.intimate > 0) { if(sd->bl.prev != NULL) - pc_calcstatus(sd,0); + status_calc_pc(sd,0); else - pc_calcstatus(sd,2); + status_calc_pc(sd,2); } - // ƒ‹[ƒg‚µ‚½Item‚𗎂Ƃ³‚¹‚é - pet_lootitem_drop(pd,sd); intif_save_petdata(sd->status.account_id,&sd->pet); pc_makesavestatus(sd); @@ -659,13 +699,15 @@ int pet_data_init(struct map_session_data *sd) nullpo_retr(1, sd); + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + if(sd->status.account_id != sd->pet.account_id || sd->status.char_id != sd->pet.char_id || sd->status.pet_id != sd->pet.pet_id) { sd->status.pet_id = 0; return 1; } - i = search_petDB_index(sd->pet.class,PET_CLASS); + i = search_petDB_index(sd->pet.class_,PET_CLASS); if(i < 0) { sd->status.pet_id = 0; return 1; @@ -682,7 +724,7 @@ int pet_data_init(struct map_session_data *sd) pd->bl.y = pd->to_y; pd->bl.id = npc_get_new_npc_id(); memcpy(pd->name,sd->pet.name,24); - pd->class = sd->pet.class; + pd->class_ = sd->pet.class_; pd->equip = sd->pet.equip; pd->dir = sd->dir; pd->speed = sd->petDB->speed; @@ -696,9 +738,13 @@ int pet_data_init(struct map_session_data *sd) pd->move_fail_count = 0; pd->next_walktime = pd->attackabletime = pd->last_thinktime = gettick(); pd->msd = sd; - + map_addiddb(&pd->bl); + // initialise + pd->state.skillbonus = -1; + run_script(pet_db[i].script,0,sd->bl.id,0); + if(sd->pet_hungry_timer != -1) pet_hungry_timer_delete(sd); if(battle_config.pet_hungry_delay_rate != 100) @@ -719,6 +765,8 @@ int pet_birth_process(struct map_session_data *sd) { nullpo_retr(1, sd); + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + if(sd->status.pet_id && sd->pet.incuvate == 1) { sd->status.pet_id = 0; return 1; @@ -747,6 +795,8 @@ int pet_birth_process(struct map_session_data *sd) clif_pet_equip(sd->pd,sd->pet.equip); clif_send_petstatus(sd); + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + return 0; } @@ -766,7 +816,7 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag) pet_birth_process(sd); else { pet_data_init(sd); - if(sd->bl.prev != NULL) { + if(sd->pd && sd->bl.prev != NULL) { map_addblock(&sd->pd->bl); clif_spawnpet(sd->pd); clif_send_petdata(sd,0,0); @@ -777,9 +827,9 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag) } if(battle_config.pet_status_support && sd->pet.intimate > 0) { if(sd->bl.prev != NULL) - pc_calcstatus(sd,0); + status_calc_pc(sd,0); else - pc_calcstatus(sd,2); + status_calc_pc(sd,2); } return 0; @@ -823,27 +873,28 @@ int pet_catch_process2(struct map_session_data *sd,int target_id) return 1; } - i = search_petDB_index(md->class,PET_CLASS); - if(md == NULL || md->bl.type != BL_MOB || md->bl.prev == NULL || i < 0 || sd->catch_target_class != md->class) { + i = search_petDB_index(md->class_,PET_CLASS); + if(md == NULL || md->bl.type != BL_MOB || md->bl.prev == NULL || i < 0 || sd->catch_target_class != md->class_) { clif_pet_rulet(sd,0); return 1; } //target_id‚É‚æ‚é“G¨—‘”»’è // if(battle_config.etc_log) -// printf("mob_id = %d, mob_class = %d\n",md->bl.id,md->class); +// printf("mob_id = %d, mob_class = %d\n",md->bl.id,md->class_); //¬Œ÷‚Ìê‡ - pet_catch_rate = (pet_db[i].capture + (sd->status.base_level - mob_db[md->class].lv)*30 + sd->paramc[5]*20)*(200 - md->hp*100/mob_db[md->class].max_hp)/100; + pet_catch_rate = (pet_db[i].capture + (sd->status.base_level - mob_db[md->class_].lv)*30 + sd->paramc[5]*20)*(200 - md->hp*100/mob_db[md->class_].max_hp)/100; if(pet_catch_rate < 1) pet_catch_rate = 1; if(battle_config.pet_catch_rate != 100) pet_catch_rate = (pet_catch_rate*battle_config.pet_catch_rate)/100; if(rand()%10000 < pet_catch_rate) { - mob_catch_delete(md,0); + mob_remove_map(md,0); + mob_setdelayspawn(md->bl.id); clif_pet_rulet(sd,1); // if(battle_config.etc_log) // printf("rulet success %d\n",target_id); - intif_create_pet(sd->status.account_id,sd->status.char_id,pet_db[i].class,mob_db[pet_db[i].class].lv, + intif_create_pet(sd->status.account_id,sd->status.char_id,pet_db[i].class_,mob_db[pet_db[i].class_].lv, pet_db[i].EggID,0,pet_db[i].intimate,100,0,1,pet_db[i].jname); } else @@ -869,7 +920,7 @@ int pet_get_egg(int account_id,int pet_id,int flag) tmp_item.nameid = pet_db[i].EggID; tmp_item.identify = 1; tmp_item.card[0] = 0xff00; - *((long *)(&tmp_item.card[1])) = pet_id; + tmp_item.card[1] = pet_id; tmp_item.card[3] = sd->pet.rename_flag; if((ret = pc_additem(sd,&tmp_item,1))) { clif_additem(sd,0,0,ret); @@ -913,7 +964,7 @@ int pet_change_name(struct map_session_data *sd,char *name) nullpo_retr(1, sd); - if(sd->pet.rename_flag == 1 && battle_config.pet_rename == 0) + if((sd->pd == NULL) || (sd->pet.rename_flag == 1 && battle_config.pet_rename == 0)) return 1; for(i=0;i<24 && name[i];i++){ @@ -951,7 +1002,7 @@ int pet_equipitem(struct map_session_data *sd,int index) else { pc_delitem(sd,index,1,0); sd->pet.equip = sd->pd->equip = nameid; - pc_calcstatus(sd,0); + status_calc_pc(sd,0); clif_pet_equip(sd->pd,nameid); } @@ -972,7 +1023,7 @@ int pet_unequipitem(struct map_session_data *sd) nameid = sd->pet.equip; sd->pet.equip = sd->pd->equip = 0; - pc_calcstatus(sd,0); + status_calc_pc(sd,0); clif_pet_equip(sd->pd,0); memset(&tmp_item,0,sizeof(tmp_item)); tmp_item.nameid = nameid; @@ -991,6 +1042,8 @@ int pet_food(struct map_session_data *sd) nullpo_retr(1, sd); + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + if(sd->petDB == NULL) return 1; i=pc_search_inventory(sd,sd->petDB->FoodID); @@ -1023,9 +1076,9 @@ int pet_food(struct map_session_data *sd) sd->pet.intimate = 0; if(battle_config.pet_status_support && t > 0) { if(sd->bl.prev != NULL) - pc_calcstatus(sd,0); + status_calc_pc(sd,0); else - pc_calcstatus(sd,2); + status_calc_pc(sd,2); } } else if(sd->pet.intimate > 1000) @@ -1048,7 +1101,9 @@ static int pet_randomwalk(struct pet_data *pd,int tick) nullpo_retr(0, pd); - speed = battle_get_speed(&pd->bl); + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + + speed = status_get_speed(&pd->bl); if(DIFF_TICK(pd->next_walktime,tick) < 0){ int i,x,y,c,d=12-pd->move_fail_count; @@ -1057,7 +1112,7 @@ static int pet_randomwalk(struct pet_data *pd,int tick) int r=rand(); x=pd->bl.x+r%(d*2+1)-d; y=pd->bl.y+r/(d*2+1)%(d*2+1)-d; - if((c=map_getcell(pd->bl.m,x,y))!=1 && c!=5 && pet_walktoxy(pd,x,y)==0){ + if((map_getcell(pd->bl.m,x,y,CELL_CHKPASS))&&( pet_walktoxy(pd,x,y)==0)){ pd->move_fail_count=0; break; } @@ -1065,7 +1120,7 @@ static int pet_randomwalk(struct pet_data *pd,int tick) pd->move_fail_count++; if(pd->move_fail_count>1000){ if(battle_config.error_log) - printf("PET cant move. hold position %d, class = %d\n",pd->bl.id,pd->class); + printf("PET cant move. hold position %d, class = %d\n",pd->bl.id,pd->class_); pd->move_fail_count=0; pet_changestate(pd,MS_DELAY,60000); return 0; @@ -1105,6 +1160,8 @@ static int pet_ai_sub_hard(struct pet_data *pd,unsigned int tick) sd = pd->msd; + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + if(pd->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL) return 0; @@ -1136,22 +1193,22 @@ static int pet_ai_sub_hard(struct pet_data *pd,unsigned int tick) pet_randomwalk(pd,tick); } else if(pd->target_id - MAX_FLOORITEM > 0) { - mode=mob_db[pd->class].mode; - race=mob_db[pd->class].race; + mode=mob_db[pd->class_].mode; + race=mob_db[pd->class_].race; md=(struct mob_data *)map_id2bl(pd->target_id); if(md == NULL || md->bl.type != BL_MOB || pd->bl.m != md->bl.m || md->bl.prev == NULL || distance(pd->bl.x,pd->bl.y,md->bl.x,md->bl.y) > 13) pet_unlocktarget(pd); - else if(mob_db[pd->class].mexp <= 0 && !(mode&0x20) && (md->option & 0x06 && race!=4 && race!=6) ) + else if(mob_db[pd->class_].mexp <= 0 && !(mode&0x20) && (md->option & 0x06 && race!=4 && race!=6) ) pet_unlocktarget(pd); - else if(!battle_check_range(&pd->bl,&md->bl,mob_db[pd->class].range)){ + else if(!battle_check_range(&pd->bl,&md->bl,mob_db[pd->class_].range)){ if(pd->timer != -1 && pd->state.state == MS_WALK && distance(pd->to_x,pd->to_y,md->bl.x,md->bl.y) < 2) return 0; if( !pet_can_reach(pd,md->bl.x,md->bl.y)) pet_unlocktarget(pd); else { i=0; - pd->speed = battle_get_speed(&pd->bl); + pd->speed = status_get_speed(&pd->bl); do { if(i==0) { // ʼn‚ÍAEGIS‚Æ“¯‚¶•û–@‚ÅŒŸõ dx=md->bl.x - pd->bl.x; @@ -1235,14 +1292,14 @@ static int pet_ai_sub_hard(struct pet_data *pd,unsigned int tick) else { if(dist <= 3 || (pd->timer != -1 && pd->state.state == MS_WALK && distance(pd->to_x,pd->to_y,sd->bl.x,sd->bl.y) < 3) ) return 0; - pd->speed = battle_get_speed(&pd->bl); + pd->speed = status_get_speed(&pd->bl); pet_calc_pos(pd,sd->bl.x,sd->bl.y,sd->dir); if(pet_walktoxy(pd,pd->to_x,pd->to_y)) pet_randomwalk(pd,tick); } } else { - pd->speed = battle_get_speed(&pd->bl); + pd->speed = status_get_speed(&pd->bl); if(pd->state.state == MS_ATTACK) pet_stopattack(pd); pet_randomwalk(pd,tick); @@ -1326,13 +1383,12 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd) clif_additem(sd,0,0,flag); map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0); } - free(ditem); + aFree(ditem); } else add_timer(gettick()+540+i,pet_delay_item_drop2,(int)ditem,0); } - pd->lootitem=NULL; - pd->lootitem=(struct item *)aCalloc(PETLOOT_SIZE,sizeof(struct item)); + memset(pd->lootitem,0,LOOTITEM_SIZE * sizeof(struct item)); pd->lootitem_count = 0; pd->lootitem_weight = 0; pd->lootitem_timer = gettick()+10000; // 10*1000ms‚ÌŠÔE‚í‚È‚¢ @@ -1349,7 +1405,7 @@ int pet_delay_item_drop2(int tid,unsigned int tick,int id,int data) map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0); - free(ditem); + aFree(ditem); return 0; } @@ -1357,29 +1413,13 @@ int pet_delay_item_drop2(int tid,unsigned int tick,int id,int data) * pet bonus giving skills [Valaris] *------------------------------------------ */ - -int pet_skill_bonus(struct map_session_data *sd,struct pet_data *pd,int type,int val,int duration,int timer,int data) -{ - if(pd==NULL || sd==NULL) - return 1; - - pd->skillbonustype=type; - pd->skillbonusval=val; - pd->skillduration=duration; - pd->skilltimer=timer; - - pd->skillbonustimer=add_timer(gettick()+pd->skilltimer*1000,pet_skill_bonus_timer,sd->bl.id,0); - - return 0; - -} - int pet_skill_bonus_timer(int tid,unsigned int tick,int id,int data) { - struct map_session_data *sd=(struct map_session_data*)map_id2bl(id); + struct map_session_data *sd=map_id2sd(id); struct pet_data *pd; + int timer = 0; - if(sd==NULL || sd->bl.type!=BL_PC) + if(sd==NULL) return 1; pd=sd->pd; @@ -1390,38 +1430,26 @@ int pet_skill_bonus_timer(int tid,unsigned int tick,int id,int data) if(pd->skillbonustimer != tid) return 0; - pd->skillbonustimer=-1; - - pc_bonus(sd,pd->skillbonustype,pd->skillbonusval); - if(pd->skillbonustype < 56) clif_updatestatus(sd,pd->skillbonustype); - pd->skillbonusduration=add_timer(gettick()+pd->skillduration*1000,pet_skill_bonus_duration,sd->bl.id,0); - - return 0; -} - -int pet_skill_bonus_duration(int tid,unsigned int tick,int id,int data) -{ - struct map_session_data *sd=(struct map_session_data*)map_id2bl(id); - struct pet_data *pd; - - if(sd==NULL || sd->bl.type!=BL_PC) - return 1; - - pd=sd->pd; - - if(pd==NULL || pd->bl.type!=BL_PET) - return 1; - - if(pd->skillbonusduration != tid) - return 0; - - pd->skillbonusduration=-1; + // determine the time for the next timer + if (pd->state.skillbonus == 0) { + // pet bonuses are not active at the moment, so, + pd->state.skillbonus = 1; + timer = pd->skillduration; // the duration for pet bonuses to be in effect + } else if (pd->state.skillbonus == 1) { + // pet bonuses are already active, so, + pd->state.skillbonus = 0; + timer = pd->skilltimer; // the duration which pet bonuses will be reactivated again + } - pc_bonus(sd,pd->skillbonustype,-pd->skillbonusval); - if(pd->skillbonustype < 56) clif_updatestatus(sd,pd->skillbonustype); + if (pd->state.skillbonus == 1 && sd->petDB) + run_script(sd->petDB->script,0,sd->bl.id,0); - pet_skill_bonus(sd,pd,pd->skillbonustype,pd->skillbonusval,pd->skillduration,pd->skilltimer,0); + // add/remove our bonuses, which will be handled by sd->petbonus[] + status_calc_pc(sd, 0); + // wait for the next timer + if (timer) pd->skillbonustimer=add_timer(gettick()+timer,pet_skill_bonus_timer,sd->bl.id,0); + return 0; } @@ -1442,7 +1470,7 @@ int pet_recovery_timer(int tid,unsigned int tick,int id,int data) return 0; if(sd->sc_data[pd->skilltype].timer != -1) - skill_status_change_end(&sd->bl,pd->skilltype,-1); + status_change_end(&sd->bl,pd->skilltype,-1); pd->skillbonustimer=add_timer(gettick()+pd->skilltimer*1000,pet_recovery_timer,sd->bl.id,0); @@ -1493,7 +1521,7 @@ int pet_mag_timer(int tid,unsigned int tick,int id,int data) if(sd->status.hp < sd->status.max_hp * pd->skilltype/100 && sd->status.sp < sd->status.max_sp * pd->skillduration/100) { clif_skill_nodamage(&pd->bl,&sd->bl,PR_MAGNIFICAT,pd->skillval,1); - skill_status_change_start(&sd->bl,SkillStatusChangeTable[PR_MAGNIFICAT],pd->skillval,0,0,0,skill_get_time(PR_MAGNIFICAT,pd->skillval),0 ); + status_change_start(&sd->bl,SkillStatusChangeTable[PR_MAGNIFICAT],pd->skillval,0,0,0,skill_get_time(PR_MAGNIFICAT,pd->skillval),0 ); } pd->skillbonustimer=add_timer(gettick()+pd->skilltimer*1000,pet_mag_timer,sd->bl.id,0); @@ -1527,19 +1555,22 @@ int pet_skillattack_timer(int tid,unsigned int tick,int id,int data) } if(md && rand()%100 < sd->pet.intimate*pd->skilltimer/100 ) { - if(pd->skilltype==6 || pd->skilltype==176) { + switch(pd->skilltype) + { + case SM_PROVOKE: + //case NPC_POISON: poison is not handled there skill_castend_nodamage_id(&pd->bl,&md->bl,pd->skilltype,pd->skillval,tick,0); - } - - else if(pd->skilltype==110){ + break; + case BS_HAMMERFALL: skill_castend_pos2(&pd->bl,md->bl.x,md->bl.y,pd->skilltype,pd->skillval,tick,0); - } - - else if(pd->skilltype==91) { + break; + case WZ_HEAVENDRIVE: skill_castend_pos2(&pd->bl,md->bl.x,md->bl.y,pd->skilltype,pd->skillval+rand()%100,tick,0); - } - else + break; + default: skill_castend_damage_id(&pd->bl,&md->bl,pd->skilltype,pd->skillval,tick,0); + break; + } pd->skillbonustimer=add_timer(gettick()+1000,pet_skillattack_timer,sd->bl.id,0); return 0; } @@ -1557,9 +1588,11 @@ int read_petdb() { FILE *fp; char line[1024]; - int i; + int nameid,i,k; int j=0; + int lines; char *filename[]={"db/pet_db.txt","db/pet_db2.txt"}; + char *str[32],*p,*np; memset(pet_db,0,sizeof(pet_db)); for(i=0;i<2;i++){ @@ -1570,20 +1603,21 @@ int read_petdb() printf("can't read %s\n",filename[i]); return -1; } + lines = 0; while(fgets(line,1020,fp)){ - int nameid,i; - char *str[32],*p,*np; + + lines++; if(line[0] == '/' && line[1] == '/') continue; - for(i=0,p=line;i<20;i++){ + for(k=0,p=line;k<20;k++){ if((np=strchr(p,','))!=NULL){ - str[i]=p; + str[k]=p; *np=0; p=np+1; } else { - str[i]=p; + str[k]=p; p+=strlen(p); } } @@ -1593,7 +1627,7 @@ int read_petdb() continue; //MobID,Name,JName,ItemID,EggID,AcceID,FoodID,"Fullness (1‰ñ‚̉a‚ł̖ž• “x‘‰Á—¦%)","HungryDeray (/min)","R_Hungry (‹ó• Žž‰a‚â‚èe–§“x‘‰Á—¦%)","R_Full (‚Æ‚Ä‚à–ž• Žž‰a‚â‚èe–§“xŒ¸—¦%)","Intimate (•ߊlŽže–§“x%)","Die (Ž€–SŽže–§“xŒ¸—¦%)","Capture (•ߊl—¦%)",(Name) - pet_db[j].class = nameid; + pet_db[j].class_ = nameid; memcpy(pet_db[j].name,str[1],24); memcpy(pet_db[j].jname,str[2],24); pet_db[j].itemID=atoi(str[3]); @@ -1618,11 +1652,12 @@ int read_petdb() pet_db[j].script = NULL; if((np=strchr(p,'{'))==NULL) continue; - pet_db[j].script = parse_script(np,0); + pet_db[j].script = parse_script((unsigned char *) np,lines); j++; } fclose(fp); - printf("read %s done (count=%d)\n",filename[i],j); + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' pets in '"CL_WHITE"%s"CL_RESET"'.\n",j,filename[i]); + ShowStatus(tmp_output); } return 0; } @@ -1639,7 +1674,6 @@ int do_init_pet(void) add_timer_func_list(pet_hungry,"pet_hungry"); add_timer_func_list(pet_ai_hard,"pet_ai_hard"); add_timer_func_list(pet_skill_bonus_timer,"pet_skill_bonus_timer"); // [Valaris] - add_timer_func_list(pet_skill_bonus_duration,"pet_skill_bonus_duration"); // [Valaris] add_timer_func_list(pet_recovery_timer,"pet_recovery_timer"); // [Valaris] add_timer_func_list(pet_mag_timer,"pet_mag_timer"); // [Valaris] add_timer_func_list(pet_heal_timer,"pet_heal_timer"); // [Valaris] @@ -1649,3 +1683,12 @@ int do_init_pet(void) return 0; } +int do_final_pet(void) { + int i; + for(i = 0;i < MAX_PET_DB; i++) { + if(pet_db[i].script) { + aFree(pet_db[i].script); + } + } + return 0; +} diff --git a/src/map/pet.h b/src/map/pet.h index 365a4490f..4d81583b1 100644 --- a/src/map/pet.h +++ b/src/map/pet.h @@ -2,11 +2,11 @@ #ifndef _PET_H_ #define _PET_H_ -#define MAX_PET_DB 100 +#define MAX_PET_DB 300 #define PETLOOT_SIZE 20 // [Valaris] struct pet_db { - int class; + int class_; char name[24],jname[24]; int itemID; int EggID; @@ -55,15 +55,15 @@ int pet_food(struct map_session_data *sd); int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd); int pet_delay_item_drop2(int tid,unsigned int tick,int id,int data); int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap); -int pet_skill_bonus(struct map_session_data *sd,struct pet_data *pd,int type,int val,int duration,int timer,int data); int pet_skill_bonus_timer(int tid,unsigned int tick,int id,int data); // [Valaris] -int pet_skill_bonus_duration(int tid,unsigned int tick,int id,int data); // [Valaris] int pet_recovery_timer(int tid,unsigned int tick,int id,int data); // [Valaris] int pet_mag_timer(int tid,unsigned int tick,int id,int data); // [Valaris] int pet_heal_timer(int tid,unsigned int tick,int id,int data); // [Valaris] int pet_skillattack_timer(int tid,unsigned int tick,int id,int data); // [Valaris] +int read_petdb(); int do_init_pet(void); +int do_final_pet(void); #endif diff --git a/src/map/script.c b/src/map/script.c index f198d42fe..9602f3505 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -14,52 +14,58 @@ #include <time.h> -#include "socket.h" -#include "timer.h" -#include "malloc.h" -#include "lock.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/malloc.h" +#include "../common/lock.h" +#include "../common/db.h" #include "map.h" #include "clif.h" #include "chrif.h" #include "itemdb.h" #include "pc.h" +#include "status.h" #include "script.h" #include "storage.h" #include "mob.h" #include "npc.h" #include "pet.h" #include "intif.h" -#include "db.h" #include "skill.h" #include "chat.h" #include "battle.h" #include "party.h" #include "guild.h" -#include "lock.h" #include "atcommand.h" #include "log.h" +#include "showmsg.h" #ifdef MEMWATCH #include "memwatch.h" #endif #define SCRIPT_BLOCK_SIZE 256 + +#define FETCH(n, t) \ + if(st->end>st->start+(n)) \ + (t)=conv_num(st,&(st->stack->stack_data[st->start+(n)])); + enum { LABEL_NEXTLINE=1,LABEL_START }; -static unsigned char * script_buf; +static unsigned char * script_buf = NULL; static int script_pos,script_size; char *str_buf; int str_pos,str_size; -static struct { +static struct str_data_struct { int type; int str; int backpatch; int label; - int (*func)(); + int (*func)(struct script_state *); int val; int next; -} *str_data; +} *str_data = NULL; int str_num=LABEL_START,str_data_size; int str_hash[16]; @@ -78,17 +84,13 @@ struct dbt* script_get_userfunc_db(){ if(!userfunc_db) userfunc_db=strdb_init(50 int scriptlabel_final(void *k,void *d,va_list ap){ return 0; } static char pos[11][100] = {"“ª","‘Ì","¶Žè","‰EŽè","ƒ[ƒu","ŒC","ƒAƒNƒZƒTƒŠ[1","ƒAƒNƒZƒTƒŠ[2","“ª2","“ª3","‘•’…‚µ‚Ä‚¢‚È‚¢"}; -static struct Script_Config { - int warn_func_no_comma; - int warn_cmd_no_comma; - int warn_func_mismatch_paramnum; - int warn_cmd_mismatch_paramnum; - int check_cmdcount; - int check_gotocount; -} script_config; +struct Script_Config script_config; + static int parse_cmd_if=0; static int parse_cmd; +extern int current_equip_item_index; //for New CARS Scripts. It contains Inventory Index of the EQUIP_SCRIPT caller item. [Lupus] + /*========================================== * ƒ[ƒJƒ‹ƒvƒƒgƒ^ƒCƒv錾 (•K—v‚È•¨‚Ì‚Ý) *------------------------------------------ @@ -155,6 +157,7 @@ int buildin_statusup2(struct script_state *st); int buildin_bonus(struct script_state *st); int buildin_bonus2(struct script_state *st); int buildin_bonus3(struct script_state *st); +int buildin_bonus4(struct script_state *st); int buildin_skill(struct script_state *st); int buildin_addtoskill(struct script_state *st); // [Valaris] int buildin_guildskill(struct script_state *st); @@ -193,6 +196,8 @@ int buildin_stopnpctimer(struct script_state *st); int buildin_startnpctimer(struct script_state *st); int buildin_setnpctimer(struct script_state *st); int buildin_getnpctimer(struct script_state *st); +int buildin_attachnpctimer(struct script_state *st); // [celest] +int buildin_detachnpctimer(struct script_state *st); // [celest] int buildin_announce(struct script_state *st); int buildin_mapannounce(struct script_state *st); int buildin_areaannounce(struct script_state *st); @@ -250,6 +255,9 @@ int buildin_failedremovecards(struct script_state *st); int buildin_marriage(struct script_state *st); int buildin_wedding_effect(struct script_state *st); int buildin_divorce(struct script_state *st); +int buildin_ispartneron(struct script_state *st); // MouseJstr +int buildin_getpartnerid(struct script_state *st); // MouseJstr +int buildin_warppartner(struct script_state *st); // MouseJstr int buildin_getitemname(struct script_state *st); int buildin_makepet(struct script_state *st); int buildin_getexp(struct script_state *st); @@ -259,6 +267,7 @@ int buildin_clearitem(struct script_state *st); int buildin_classchange(struct script_state *st); int buildin_misceffect(struct script_state *st); int buildin_soundeffect(struct script_state *st); +int buildin_soundeffectall(struct script_state *st); int buildin_setcastledata(struct script_state *st); int buildin_mapwarp(struct script_state *st); int buildin_inittimer(struct script_state *st); @@ -274,6 +283,7 @@ int buildin_petloot(struct script_state *st); // pet looting [Valaris] int buildin_petheal(struct script_state *st); // pet healing [Valaris] int buildin_petmag(struct script_state *st); // pet magnificat [Valaris] int buildin_petskillattack(struct script_state *st); // pet skill attacks [Valaris] +int buildin_skilleffect(struct script_state *st); // skill effects [Celest] int buildin_npcskilleffect(struct script_state *st); // skill effects for npcs [Valaris] int buildin_specialeffect(struct script_state *st); // special effect script [Valaris] int buildin_specialeffect2(struct script_state *st); // special effect script [Valaris] @@ -289,6 +299,28 @@ int buildin_npcspeed(struct script_state *st); // [Valaris] int buildin_npcwalkto(struct script_state *st); // [Valaris] int buildin_npcstop(struct script_state *st); // [Valaris] int buildin_getmapxy(struct script_state *st); //get map position for player/npc/pet/mob by Lorky [Lupus] +int buildin_checkoption1(struct script_state *st); // [celest] +int buildin_checkoption2(struct script_state *st); // [celest] +int buildin_guildgetexp(struct script_state *st); // [celest] +int buildin_skilluseid(struct script_state *st); // originally by Qamera [celest] +int buildin_skillusepos(struct script_state *st); // originally by Qamera [celest] +int buildin_logmes(struct script_state *st); // [Lupus] +int buildin_summon(struct script_state *st); // [celest] +int buildin_isnight(struct script_state *st); // [celest] +int buildin_isday(struct script_state *st); // [celest] +int buildin_isequipped(struct script_state *st); // [celest] +int buildin_isequippedcnt(struct script_state *st); // [celest] +int buildin_cardscnt(struct script_state *st); // [Lupus] +int buildin_getrefine(struct script_state *st); // [celest] +int buildin_getusersname(struct script_state *st); //jA commands added [Lupus] +int buildin_dispbottom(struct script_state *st); +int buildin_recovery(struct script_state *st); +int buildin_getpetinfo(struct script_state *st); +int buildin_checkequipedcard(struct script_state *st); +int buildin_globalmes(struct script_state *st); +int buildin_jump_zero(struct script_state *st); +int buildin_select(struct script_state *st); +int buildin_getmapmobs(struct script_state *st); //jA addition end void push_val(struct script_stack *stack,int type,int val); @@ -297,8 +329,15 @@ int run_func(struct script_state *st); int mapreg_setreg(int num,int val); int mapreg_setregstr(int num,const char *str); +#ifdef PCRE_SUPPORT +int buildin_defpattern(struct script_state *st); // MouseJstr +int buildin_activatepset(struct script_state *st); // MouseJstr +int buildin_deactivatepset(struct script_state *st); // MouseJstr +int buildin_deletepset(struct script_state *st); // MouseJstr +#endif + struct { - int (*func)(); + int (*func)(struct script_state *); char *name; char *arg; } buildin_func[]={ @@ -363,6 +402,7 @@ struct { {buildin_bonus,"bonus","ii"}, {buildin_bonus2,"bonus2","iii"}, {buildin_bonus3,"bonus3","iiii"}, + {buildin_bonus4,"bonus4","iiiii"}, {buildin_skill,"skill","ii*"}, {buildin_addtoskill,"addtoskill","ii*"}, // [Valaris] {buildin_guildskill,"guildskill","ii"}, @@ -403,6 +443,8 @@ struct { {buildin_startnpctimer,"startnpctimer","*"}, {buildin_setnpctimer,"setnpctimer","*"}, {buildin_getnpctimer,"getnpctimer","i*"}, + {buildin_attachnpctimer,"attachnpctimer","*"}, // attached the player id to the npc timer [Celest] + {buildin_detachnpctimer,"detachnpctimer","*"}, // detached the player id from the npc timer [Celest] {buildin_announce,"announce","si"}, {buildin_mapannounce,"mapannounce","ssi"}, {buildin_areaannounce,"areaannounce","siiiisi"}, @@ -460,7 +502,10 @@ struct { {buildin_failedremovecards,"failedremovecards","ii"}, {buildin_marriage,"marriage","s"}, {buildin_wedding_effect,"wedding",""}, - {buildin_divorce,"divorce",""}, + {buildin_divorce,"divorce","*"}, + {buildin_ispartneron,"ispartneron","*"}, + {buildin_getpartnerid,"getpartnerid","*"}, + {buildin_warppartner,"warppartner","sii"}, {buildin_getitemname,"getitemname","i"}, {buildin_makepet,"makepet","i"}, {buildin_getexp,"getexp","ii"}, @@ -470,6 +515,7 @@ struct { {buildin_classchange,"classchange","ii"}, {buildin_misceffect,"misceffect","i"}, {buildin_soundeffect,"soundeffect","si"}, + {buildin_soundeffectall,"soundeffectall","si"}, // SoundEffectAll [Codemaster] {buildin_strmobinfo,"strmobinfo","ii"}, // display mob data [Valaris] {buildin_guardian,"guardian","siisii*i"}, // summon guardians {buildin_guardianinfo,"guardianinfo","i"}, // display guardian data [Valaris] @@ -479,6 +525,7 @@ struct { {buildin_petheal,"petheal","iii"}, // [Valaris] {buildin_petmag,"petmag","iiii"}, // [Valaris] {buildin_petskillattack,"petskillattack","iiii"}, // [Valaris] + {buildin_skilleffect,"skilleffect","ii"}, // skill effect [Celest] {buildin_npcskilleffect,"npcskilleffect","iiii"}, // npc skill effect [Valaris] {buildin_specialeffect,"specialeffect","i"}, // npc skill effect [Valaris] {buildin_specialeffect2,"specialeffect2","i"}, // skill effect on players[Valaris] @@ -493,16 +540,43 @@ struct { {buildin_npctalk,"npctalk","*"}, // [Valaris] {buildin_hasitems,"hasitems","*"}, // [Valaris] {buildin_mobcount,"mobcount","ss"}, - {buildin_getlook,"getlook","i"}, + {buildin_getlook,"getlook","i"}, {buildin_getsavepoint,"getsavepoint","i"}, {buildin_npcspeed,"npcspeed","i"}, // [Valaris] {buildin_npcwalkto,"npcwalkto","ii"}, // [Valaris] {buildin_npcstop,"npcstop",""}, // [Valaris] {buildin_getmapxy,"getmapxy","siii*"}, //by Lorky [Lupus] + {buildin_checkoption1,"checkoption1","i"}, + {buildin_checkoption2,"checkoption2","i"}, + {buildin_guildgetexp,"guildgetexp","i"}, + {buildin_skilluseid,"skilluseid","ii"}, // originally by Qamera [Celest] + {buildin_skilluseid,"doskill","ii"}, // since a lot of scripts would already use 'doskill'... + {buildin_skillusepos,"skillusepos","iiii"}, // [Celest] + {buildin_logmes,"logmes","s"}, //this command actls as MES but prints info into LOG file either SQL/TXT [Lupus] + {buildin_summon,"summon","si*"}, // summons a slave monster [Celest] + {buildin_isnight,"isnight",""}, // check whether it is night time [Celest] + {buildin_isday,"isday",""}, // check whether it is day time [Celest] + {buildin_isequipped,"isequipped","i*"}, // check whether another item/card has been equipped [Celest] + {buildin_isequippedcnt,"isequippedcnt","i*"}, // check how many items/cards are being equipped [Celest] + {buildin_cardscnt,"cardscnt","i*"}, // check how many items/cards are being equipped in the same arm [Lupus] + {buildin_getrefine,"getrefine",""}, // returns the refined number of the current item, or an item with index specified [celest] +#ifdef PCRE_SUPPORT + {buildin_defpattern, "defpattern", "iss"}, // Define pattern to listen for [MouseJstr] + {buildin_activatepset, "activatepset", "i"}, // Activate a pattern set [MouseJstr] + {buildin_deactivatepset, "deactivatepset", "i"}, // Deactive a pattern set [MouseJstr] + {buildin_deletepset, "deletepset", "i"}, // Delete a pattern set [MouseJstr] +#endif + {buildin_dispbottom,"dispbottom","s"}, //added from jA [Lupus] + {buildin_getusersname,"getusersname","*"}, + {buildin_recovery,"recovery",""}, + {buildin_getpetinfo,"getpetinfo","i"}, + {buildin_checkequipedcard,"checkequipedcard","i"}, + {buildin_jump_zero,"jump_zero","ii"}, //for future jA script compatibility + {buildin_select,"select","*"}, //for future jA script compatibility + {buildin_globalmes,"globalmes","s*"}, + {buildin_getmapmobs,"getmapmobs","s"}, //end jA addition {NULL,NULL,NULL}, }; -int buildin_message(struct script_state *st); // [MouseJstr] - enum { C_NOP,C_POS,C_INT,C_PARAM,C_FUNC,C_STR,C_CONSTSTR,C_ARG, @@ -536,7 +610,7 @@ static int search_str(const unsigned char *p) int i; i=str_hash[calc_hash(p)]; while(i){ - if(strcmp(str_buf+str_data[i].str,p)==0){ + if(strcmp(str_buf+str_data[i].str,(char *) p)==0){ return i; } i=str_data[i].next; @@ -554,14 +628,14 @@ static int add_str(const unsigned char *p) int i; char *lowcase; - lowcase=strdup(p); + lowcase=aStrdup((char *) p); for(i=0;lowcase[i];i++) lowcase[i]=tolower(lowcase[i]); - if((i=search_str(lowcase))>=0){ - free(lowcase); + if((i=search_str((unsigned char *) lowcase))>=0){ + aFree(lowcase); return i; } - free(lowcase); + aFree(lowcase); i=calc_hash(p); if(str_hash[i]==0){ @@ -569,7 +643,7 @@ static int add_str(const unsigned char *p) } else { i=str_hash[i]; for(;;){ - if(strcmp(str_buf+str_data[i].str,p)==0){ + if(strcmp(str_buf+str_data[i].str,(char *) p)==0){ return i; } if(str_data[i].next==0) @@ -580,22 +654,22 @@ static int add_str(const unsigned char *p) } if(str_num>=str_data_size){ str_data_size+=128; - str_data=aRealloc(str_data,sizeof(str_data[0])*str_data_size); + str_data=(struct str_data_struct *) aRealloc(str_data,sizeof(str_data[0])*str_data_size); memset(str_data + (str_data_size - 128), '\0', 128); } - while(str_pos+strlen(p)+1>=str_size){ + while(str_pos+(int)strlen((char *) p)+1>=str_size){ str_size+=256; str_buf=(char *)aRealloc(str_buf,str_size); memset(str_buf + (str_size - 256), '\0', 256); } - strcpy(str_buf+str_pos,p); + strcpy(str_buf+str_pos, (char *) p); str_data[str_num].type=C_NOP; str_data[str_num].str=str_pos; str_data[str_num].next=0; str_data[str_num].func=NULL; str_data[str_num].backpatch=-1; str_data[str_num].label=-1; - str_pos+=strlen(p)+1; + str_pos+=strlen( (char *) p)+1; return str_num++; } @@ -608,7 +682,7 @@ static void check_script_buf(int size) { if(script_pos+size>=script_size){ script_size+=SCRIPT_BLOCK_SIZE; - script_buf=(char *)aRealloc(script_buf,script_size); + script_buf=(unsigned char *)aRealloc(script_buf,script_size); memset(script_buf + script_size - SCRIPT_BLOCK_SIZE, '\0', SCRIPT_BLOCK_SIZE); } @@ -769,13 +843,17 @@ static void disp_error_message(const char *mes,const unsigned char *pos) for(line=startline,p=startptr;p && *p;line++){ linestart=p; - lineend=strchr(p,'\n'); + lineend=(unsigned char *) strchr((char *) p,'\n'); if(lineend){ c=*lineend; *lineend=0; } if(lineend==NULL || pos<lineend){ - printf("%s line %d : ",mes,line); + if (current_file) { + printf("%s in "CL_WHITE"\'%s\'"CL_RESET" line "CL_WHITE"\'%d\'"CL_RESET" : ", mes, current_file, line); + } else { + printf("%s line "CL_WHITE"\'%d\'"CL_RESET" : ", mes, line); + } for(i=0;(linestart[i]!='\r') && (linestart[i]!='\n') && linestart[i];i++){ if(linestart+i!=pos) printf("%c",linestart[i]); @@ -819,9 +897,9 @@ unsigned char* parse_simpleexpr(unsigned char *p) } } else if(isdigit(*p) || ((*p=='-' || *p=='+') && isdigit(p[1]))){ char *np; - i=strtoul(p,&np,0); + i=strtoul((char *) p,&np,0); add_scripti(i); - p=np; + p=(unsigned char *) np; } else if(*p=='"'){ add_scriptc(C_STR); p++; @@ -848,12 +926,12 @@ unsigned char* parse_simpleexpr(unsigned char *p) disp_error_message("unexpected character",p); exit(1); } - p2=skip_word(p); + p2=(char *) skip_word(p); c=*p2; *p2=0; // –¼‘O‚ðadd_str‚·‚é l=add_str(p); parse_cmd=l; // warn_*_mismatch_paramnum‚Ì‚½‚߂ɕK—v - if(l==search_str("if")) // warn_cmd_no_comma‚Ì‚½‚߂ɕK—v + if(l== search_str((unsigned char *) "if")) // warn_cmd_no_comma‚Ì‚½‚߂ɕK—v parse_cmd_if++; /* // ”pŽ~—\’è‚Ìl14/l15,‚¨‚æ‚уvƒŒƒtƒBƒbƒNƒX‚Œ‚ÌŒx @@ -864,11 +942,12 @@ unsigned char* parse_simpleexpr(unsigned char *p) disp_error_message("prefix 'l' is DEPRECATED. use prefix '@' instead.",p2); } */ - *p2=c; p=p2; + *p2=c; + p=(unsigned char *) p2; if(str_data[l].type!=C_FUNC && c=='['){ // array(name[i] => getelementofarray(name,i) ) - add_scriptl(search_str("getelementofarray")); + add_scriptl(search_str((unsigned char *) "getelementofarray")); add_scriptc(C_ARG); add_scriptl(l); p=parse_subexpr(p+1,-1); @@ -906,14 +985,14 @@ unsigned char* parse_subexpr(unsigned char *p,int limit) p=skip_space(p); if(*p=='-'){ - tmpp=skip_space(p+1); + tmpp=(char *) skip_space((unsigned char *) (p+1)); if(*tmpp==';' || *tmpp==','){ add_scriptl(LABEL_NEXTLINE); p++; return p; } } - tmpp=p; + tmpp=(char *) p; if((op=C_NEG,*p=='-') || (op=C_LNOT,*p=='!') || (op=C_NOT,*p=='~')){ p=parse_subexpr(p+1,100); add_scriptc(op); @@ -945,13 +1024,13 @@ unsigned char* parse_subexpr(unsigned char *p,int limit) const char *plist[128]; if( str_data[func].type!=C_FUNC ){ - disp_error_message("expect function",tmpp); + disp_error_message("expect function",(unsigned char *) tmpp); exit(0); } add_scriptc(C_ARG); do { - plist[i]=p; + plist[i]=(char *) p; p=parse_subexpr(p,-1); p=skip_space(p); if(*p==',') p++; @@ -961,7 +1040,7 @@ unsigned char* parse_subexpr(unsigned char *p,int limit) p=skip_space(p); i++; } while(*p && *p!=')' && i<128); - plist[i]=p; + plist[i]=(char *) p; if(*(p++)!=')'){ disp_error_message("func request '(' ')'",p); exit(1); @@ -972,7 +1051,7 @@ unsigned char* parse_subexpr(unsigned char *p,int limit) int j=0; for(j=0;arg[j];j++) if(arg[j]=='*')break; if( (arg[j]==0 && i!=j) || (arg[j]=='*' && i<j) ){ - disp_error_message("illegal number of parameters",plist[(i<j)?i:j]); + disp_error_message("illegal number of parameters",(unsigned char *) (plist[(i<j)?i:j])); } } } else { @@ -1029,19 +1108,19 @@ unsigned char* parse_line(unsigned char *p) parse_cmd_if=0; // warn_cmd_no_comma‚Ì‚½‚߂ɕK—v // ʼn‚ÍŠÖ”–¼ - p2=p; + p2=(char *) p; p=parse_simpleexpr(p); p=skip_space(p); cmd=parse_cmd; if( str_data[cmd].type!=C_FUNC ){ - disp_error_message("expect command",p2); + disp_error_message("expect command",(unsigned char *) p2); // exit(0); } add_scriptc(C_ARG); while(p && *p && *p!=';' && i<128){ - plist[i]=p; + plist[i]=(char *) p; p=parse_expr(p); p=skip_space(p); @@ -1053,7 +1132,7 @@ unsigned char* parse_line(unsigned char *p) p=skip_space(p); i++; } - plist[i]=p; + plist[i]=(char *) p; if(!p || *(p++)!=';'){ disp_error_message("need ';'",p); exit(1); @@ -1065,7 +1144,7 @@ unsigned char* parse_line(unsigned char *p) int j=0; for(j=0;arg[j];j++) if(arg[j]=='*')break; if( (arg[j]==0 && i!=j) || (arg[j]=='*' && i<j) ){ - disp_error_message("illegal number of parameters",plist[(i<j)?i:j]); + disp_error_message("illegal number of parameters",(unsigned char *) (plist[(i<j)?i:j])); } } @@ -1081,7 +1160,7 @@ static void add_buildin_func(void) { int i,n; for(i=0;buildin_func[i].func;i++){ - n=add_str(buildin_func[i].name); + n=add_str((unsigned char *) buildin_func[i].name); str_data[n].type=C_FUNC; str_data[n].val=i; str_data[n].func=buildin_func[i].func; @@ -1111,7 +1190,7 @@ static void read_constdb(void) sscanf(line,"%[A-Za-z0-9_] %d %d",name,&val,&type)>=2){ for(i=0;name[i];i++) name[i]=tolower(name[i]); - n=add_str(name); + n=add_str((const unsigned char *) name); if(type==0) str_data[n].type=C_INT; else @@ -1126,7 +1205,7 @@ static void read_constdb(void) * ƒXƒNƒŠƒvƒg‚̉ðÍ *------------------------------------------ */ -unsigned char* parse_script(unsigned char *src,int line) +char* parse_script(unsigned char *src,int line) { unsigned char *p,*tmpp; int i; @@ -1137,7 +1216,7 @@ unsigned char* parse_script(unsigned char *src,int line) read_constdb(); } first=0; - script_buf=(unsigned char *)aCalloc(SCRIPT_BLOCK_SIZE,sizeof(unsigned char)); + script_buf=(unsigned char *)aCallocA(SCRIPT_BLOCK_SIZE,sizeof(unsigned char)); script_pos=0; script_size=SCRIPT_BLOCK_SIZE; str_data[LABEL_NEXTLINE].type=C_NOP; @@ -1202,7 +1281,7 @@ unsigned char* parse_script(unsigned char *src,int line) add_scriptc(C_NOP); script_size = script_pos; - script_buf=(char *)aRealloc(script_buf,script_pos + 1); + script_buf=(unsigned char *)aRealloc(script_buf,script_pos + 1); // –¢‰ðŒˆ‚̃‰ƒxƒ‹‚ð‰ðŒˆ for(i=LABEL_START;i<str_num;i++){ @@ -1229,7 +1308,7 @@ unsigned char* parse_script(unsigned char *src,int line) printf("\n"); #endif - return script_buf; + return (char *) script_buf; } // @@ -1364,6 +1443,11 @@ static int set_reg(struct map_session_data *sd,int num,char *name,void *v) return 0; } +int set_var(struct map_session_data *sd, char *name, void *val) +{ + return set_reg(sd, add_str((unsigned char *) name), name, val); +} + /*========================================== * •¶Žš—ñ‚ւ̕ϊ· *------------------------------------------ @@ -1373,7 +1457,7 @@ char* conv_str(struct script_state *st,struct script_data *data) get_val(st,data); if(data->type==C_INT){ char *buf; - buf=(char *)aCalloc(16,sizeof(char)); + buf=(char *)aCallocA(16,sizeof(char)); sprintf(buf,"%d",data->u.num); data->type=C_STR; data->u.str=buf; @@ -1399,7 +1483,7 @@ int conv_num(struct script_state *st,struct script_data *data) p=data->u.str; data->u.num = atoi(p); if(data->type==C_STR) - free(p); + aFree(p); data->type=C_INT; } return data->u.num; @@ -1441,7 +1525,7 @@ void push_str(struct script_stack *stack,int type,unsigned char *str) // if(battle_config.etc_log) // printf("push (%d,%x)-> %d\n",type,str,stack->sp); stack->stack_data[stack->sp].type=type; - stack->stack_data[stack->sp].u.str=str; + stack->stack_data[stack->sp].u.str=(char *) str; stack->sp++; } @@ -1453,10 +1537,10 @@ void push_copy(struct script_stack *stack,int pos) { switch(stack->stack_data[pos].type){ case C_CONSTSTR: - push_str(stack,C_CONSTSTR,stack->stack_data[pos].u.str); + push_str(stack,C_CONSTSTR,(unsigned char *) stack->stack_data[pos].u.str); break; case C_STR: - push_str(stack,C_STR,strdup(stack->stack_data[pos].u.str)); + push_str(stack,C_STR,(unsigned char *) aStrdup(stack->stack_data[pos].u.str)); break; default: push_val(stack,stack->stack_data[pos].type,stack->stack_data[pos].u.num); @@ -1473,7 +1557,7 @@ void pop_stack(struct script_stack* stack,int start,int end) int i; for(i=start;i<end;i++){ if(stack->stack_data[i].type==C_STR){ - free(stack->stack_data[i].u.str); + aFree(stack->stack_data[i].u.str); } } if(stack->sp>end){ @@ -1505,7 +1589,7 @@ int buildin_goto(struct script_state *st) int pos; if( st->stack->stack_data[st->start+2].type!=C_POS ){ - printf("script: goto: not label !\n"); + printf("script: goto: not label!\n"); st->state=END; return 0; } @@ -1525,7 +1609,7 @@ int buildin_callfunc(struct script_state *st) char *scr; char *str=conv_str(st,& (st->stack->stack_data[st->start+2])); - if( (scr=strdb_search(script_get_userfunc_db(),str)) ){ + if( (scr=(char *) strdb_search(script_get_userfunc_db(),str)) ){ int i,j; for(i=st->start+3,j=0;i<st->end;i++,j++) push_copy(st->stack,i); @@ -1641,7 +1725,7 @@ int buildin_menu(struct script_state *st) char *buf; int len,i; struct map_session_data *sd; - + sd=script_rid2sd(st); if(sd->state.menu_or_input==0){ @@ -1651,21 +1735,21 @@ int buildin_menu(struct script_state *st) conv_str(st,& (st->stack->stack_data[i])); len+=strlen(st->stack->stack_data[i].u.str)+1; } - buf=(char *)aCalloc(len,sizeof(char)); + buf=(char *)aCallocA(len+1,sizeof(char)); buf[0]=0; for(i=st->start+2,len=0;i<st->end;i+=2){ strcat(buf,st->stack->stack_data[i].u.str); strcat(buf,":"); } clif_scriptmenu(script_rid2sd(st),st->oid,buf); - free(buf); + aFree(buf); } else if(sd->npc_menu==0xff){ // cansel sd->state.menu_or_input=0; st->state=END; } else { // goto“®ì // ragemuŒÝŠ·‚Ì‚½‚ß - pc_setreg(sd,add_str("l15"),sd->npc_menu); - pc_setreg(sd,add_str("@menu"),sd->npc_menu); + pc_setreg(sd,add_str((unsigned char *) "l15"),sd->npc_menu); + pc_setreg(sd,add_str((unsigned char *) "@menu"),sd->npc_menu); sd->state.menu_or_input=0; if(sd->npc_menu>0 && sd->npc_menu<(st->end-st->start)/2){ int pos; @@ -1688,21 +1772,23 @@ int buildin_menu(struct script_state *st) */ int buildin_rand(struct script_state *st) { - int range,min,max; + int range; - if(st->end>st->start+3){ - min=conv_num(st,& (st->stack->stack_data[st->start+2])); - max=conv_num(st,& (st->stack->stack_data[st->start+3])); - if(max<min){ - int tmp; - tmp=min; - min=max; - max=tmp; + if (st->end > st->start+3){ + int min, max; + min = conv_num(st,& (st->stack->stack_data[st->start+2])); + max = conv_num(st,& (st->stack->stack_data[st->start+3])); + if (max < min){ + int tmp = min; + min = max; + max = tmp; } - range=max-min+1; + range = max - min + 1; + if (range == 0) range = 1; push_val(st->stack,C_INT,rand()%range+min); } else { - range=conv_num(st,& (st->stack->stack_data[st->start+2])); + range = conv_num(st,& (st->stack->stack_data[st->start+2])); + if (range == 0) range = 1; push_val(st->stack,C_INT,rand()%range); } return 0; @@ -1846,7 +1932,7 @@ int buildin_input(struct script_state *st) { struct map_session_data *sd=NULL; int num=(st->end>st->start+2)?st->stack->stack_data[st->start+2].u.num:0; - char *name=(st->end>st->start+2)?str_buf+str_data[num&0x00ffffff].str:""; + char *name=(char *) ((st->end>st->start+2)?str_buf+str_data[num&0x00ffffff].str:""); // char prefix=*name; char postfix=name[strlen(name)-1]; @@ -1877,7 +1963,7 @@ int buildin_input(struct script_state *st) set_reg(sd,num,name,(void*)sd->npc_amount); } else { // ragemuŒÝŠ·‚Ì‚½‚ß - pc_setreg(sd,add_str("l14"),sd->npc_amount); + pc_setreg(sd,add_str((unsigned char *) "l14"),sd->npc_amount); } } } else { @@ -2102,7 +2188,7 @@ int buildin_deletearray(struct script_state *st) } for(;i<(128-(num>>24));i++){ if( postfix!='$' ) set_reg(sd,num+(i<<24),name, 0); - if( postfix=='$' ) set_reg(sd,num+(i<<24),name, ""); + if( postfix=='$' ) set_reg(sd,num+(i<<24),name, (void *) ""); } return 0; } @@ -2274,7 +2360,7 @@ int buildin_checkweight(struct script_state *st) */ int buildin_getitem(struct script_state *st) { - int nameid,amount,flag = 0; + int nameid,nameidsrc,amount,flag = 0; struct item item_tmp; struct map_session_data *sd; struct script_data *data; @@ -2296,12 +2382,12 @@ int buildin_getitem(struct script_state *st) return 0; //return if amount <=0, skip the useles iteration } //Violet Box, Blue Box, etc - random item pick - if(nameid<0) { // ƒ‰ƒ“ƒ_ƒ€ + if((nameidsrc = nameid)<0) { // Save real ID of the source Box [Lupus] nameid=itemdb_searchrandomid(-nameid); - #ifndef TXT_ONLY + if(log_config.present > 0) - log_present(sd, -nameid, nameid); - #endif //USE_SQL + log_present(sd, -nameidsrc, nameid); //fixed missing ID by Lupus + flag = 1; } @@ -2318,7 +2404,8 @@ int buildin_getitem(struct script_state *st) return 0; if((flag = pc_additem(sd,&item_tmp,amount))) { clif_additem(sd,0,0,flag); - map_addflooritem(&item_tmp,amount,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); + if(!pc_candrop(sd,nameid)) + map_addflooritem(&item_tmp,amount,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); } } @@ -2499,7 +2586,7 @@ int buildin_delitem(struct script_state *st) if(sd->inventory_data[i]->type==7 && sd->status.inventory[i].card[0] == (short)0xff00 && search_petDB_index(nameid, PET_EGG) >= 0 ){ intif_delete_petdata(*((long *)(&sd->status.inventory[i].card[1]))); //clear egg flag. so it won't be put in IMPORTANT items (eggs look like item with 2 cards ^_^) - sd->status.inventory[i].card[1] = sd->status.inventory[i].card[0] = 0; + sd->status.inventory[i].card[1] = sd->status.inventory[i].card[0] = 0; //now this egg'll be deleted as a common unimportant item } //is this item important? does it have cards? or Player's name? or Refined/Upgraded @@ -2528,7 +2615,7 @@ int buildin_delitem(struct script_state *st) continue; if(sd->status.inventory[i].amount>=amount){ - pc_delitem(sd,i,amount,0); + pc_delitem(sd,i,amount,0); return 0; //we deleted exact amount of items. now exit } else { amount-=sd->status.inventory[i].amount; @@ -2604,7 +2691,7 @@ char *buildin_getpartyname_sub(int party_id) if(p!=NULL){ char *buf; - buf=(char *)aCalloc(24,sizeof(char)); + buf=(char *)aCallocA(24,sizeof(char)); strcpy(buf,p->name); return buf; } @@ -2619,9 +2706,9 @@ int buildin_getpartyname(struct script_state *st) party_id=conv_num(st,& (st->stack->stack_data[st->start+2])); name=buildin_getpartyname_sub(party_id); if(name!=0) - push_str(st->stack,C_STR,name); + push_str(st->stack,C_STR,(unsigned char *)name); else - push_str(st->stack,C_CONSTSTR,"null"); + push_str(st->stack,C_CONSTSTR, (unsigned char *) "null"); return 0; } @@ -2641,12 +2728,12 @@ int buildin_getpartymember(struct script_state *st) for(i=0;i<MAX_PARTY;i++){ if(p->member[i].account_id){ // printf("name:%s %d\n",p->member[i].name,i); - mapreg_setregstr(add_str("$@partymembername$")+(i<<24),p->member[i].name); + mapreg_setregstr(add_str((unsigned char *) "$@partymembername$")+(i<<24),p->member[i].name); j++; } } } - mapreg_setreg(add_str("$@partymembercount"),j); + mapreg_setreg(add_str((unsigned char *) "$@partymembercount"),j); return 0; } @@ -2661,7 +2748,7 @@ char *buildin_getguildname_sub(int guild_id) if(g!=NULL){ char *buf; - buf=(char *)aCalloc(24,sizeof(char)); + buf=(char *)aCallocA(24,sizeof(char)); strcpy(buf,g->name); return buf; } @@ -2673,9 +2760,9 @@ int buildin_getguildname(struct script_state *st) int guild_id=conv_num(st,& (st->stack->stack_data[st->start+2])); name=buildin_getguildname_sub(guild_id); if(name!=0) - push_str(st->stack,C_STR,name); + push_str(st->stack,C_STR,(unsigned char *) name); else - push_str(st->stack,C_CONSTSTR,"null"); + push_str(st->stack,C_CONSTSTR,(unsigned char *) "null"); return 0; } @@ -2690,7 +2777,7 @@ char *buildin_getguildmaster_sub(int guild_id) if(g!=NULL){ char *buf; - buf=(char *)aCalloc(24,sizeof(char)); + buf=(char *)aCallocA(24,sizeof(char)); strncpy(buf,g->master, 23); return buf; } @@ -2703,9 +2790,9 @@ int buildin_getguildmaster(struct script_state *st) int guild_id=conv_num(st,& (st->stack->stack_data[st->start+2])); master=buildin_getguildmaster_sub(guild_id); if(master!=0) - push_str(st->stack,C_STR,master); + push_str(st->stack,C_STR,(unsigned char *) master); else - push_str(st->stack,C_CONSTSTR,"null"); + push_str(st->stack,C_CONSTSTR,(unsigned char *) "null"); return 0; } @@ -2740,25 +2827,25 @@ int buildin_strcharinfo(struct script_state *st) num=conv_num(st,& (st->stack->stack_data[st->start+2])); if(num==0){ char *buf; - buf=(char *)aCalloc(24,sizeof(char)); + buf=(char *)aCallocA(24,sizeof(char)); strncpy(buf,sd->status.name, 23); - push_str(st->stack,C_STR,buf); + push_str(st->stack,C_STR,(unsigned char *) buf); } if(num==1){ char *buf; buf=buildin_getpartyname_sub(sd->status.party_id); if(buf!=0) - push_str(st->stack,C_STR,buf); + push_str(st->stack,C_STR,(unsigned char *) buf); else - push_str(st->stack,C_CONSTSTR,""); + push_str(st->stack,C_CONSTSTR,(unsigned char *) ""); } if(num==2){ char *buf; buf=buildin_getguildname_sub(sd->status.guild_id); if(buf!=0) - push_str(st->stack,C_STR,buf); + push_str(st->stack,C_STR,(unsigned char *) buf); else - push_str(st->stack,C_CONSTSTR,""); + push_str(st->stack,C_CONSTSTR,(unsigned char *) ""); } return 0; @@ -2807,7 +2894,7 @@ int buildin_getequipname(struct script_state *st) struct item_data* item; char *buf; - buf=(char *)aCalloc(64,sizeof(char)); + buf=(char *)aCallocA(64,sizeof(char)); sd=script_rid2sd(st); num=conv_num(st,& (st->stack->stack_data[st->start+2])); i=pc_checkequip(sd,equip[num-1]); @@ -2820,7 +2907,7 @@ int buildin_getequipname(struct script_state *st) }else{ sprintf(buf,"%s-[%s]",pos[num-1],pos[10]); } - push_str(st->stack,C_STR,buf); + push_str(st->stack,C_STR,(unsigned char *) buf); return 0; } @@ -2833,9 +2920,9 @@ int buildin_getbrokenid(struct script_state *st) { int i,num,id=0,brokencounter=0; struct map_session_data *sd; - + sd=script_rid2sd(st); - + num=conv_num(st,& (st->stack->stack_data[st->start+2])); for(i=0; i<MAX_INVENTORY; i++) { if(sd->status.inventory[i].attribute==1){ @@ -2846,7 +2933,7 @@ int buildin_getbrokenid(struct script_state *st) } } } - + push_val(st->stack,C_INT,id); return 0; @@ -2864,7 +2951,7 @@ int buildin_repair(struct script_state *st) sd=script_rid2sd(st); - + num=conv_num(st,& (st->stack->stack_data[st->start+2])); for(i=0; i<MAX_INVENTORY; i++) { if(sd->status.inventory[i].attribute==1){ @@ -2916,10 +3003,13 @@ int buildin_getequipisenableref(struct script_state *st) num=conv_num(st,& (st->stack->stack_data[st->start+2])); sd=script_rid2sd(st); i=pc_checkequip(sd,equip[num-1]); - if(i >= 0 && num<7 && sd->inventory_data[i] && (num!=1 + if(i >= 0 && num<7 && sd->inventory_data[i] && !sd->inventory_data[i]->flag.no_refine) + // replaced by Celest + /*(num!=1 || sd->inventory_data[i]->def > 1 || (sd->inventory_data[i]->def==1 && sd->inventory_data[i]->equip_script==NULL) - || (sd->inventory_data[i]->def<=0 && sd->inventory_data[i]->equip_script!=NULL))) + || (sd->inventory_data[i]->def<=0 && sd->inventory_data[i]->equip_script!=NULL)))*/ + { push_val(st->stack,C_INT,1); } else { @@ -3002,7 +3092,7 @@ int buildin_getequippercentrefinery(struct script_state *st) sd=script_rid2sd(st); i=pc_checkequip(sd,equip[num-1]); if(i >= 0) - push_val(st->stack,C_INT,pc_percentrefinery(sd,&sd->status.inventory[i])); + push_val(st->stack,C_INT,status_percentrefinery(sd,&sd->status.inventory[i])); else push_val(st->stack,C_INT,0); @@ -3024,13 +3114,11 @@ int buildin_successrefitem(struct script_state *st) if(i >= 0) { ep=sd->status.inventory[i].equip; - #ifndef TXT_ONLY if(log_config.refine > 0) log_refine(sd, i, 1); - #endif //USE_SQL sd->status.inventory[i].refine++; - pc_unequipitem(sd,i,0, BF_NORMAL); + pc_unequipitem(sd,i,2); clif_refine(sd->fd,sd,0,i,sd->status.inventory[i].refine); clif_delitem(sd,i,1); clif_additem(sd,i,1,0); @@ -3054,13 +3142,11 @@ int buildin_failedrefitem(struct script_state *st) sd=script_rid2sd(st); i=pc_checkequip(sd,equip[num-1]); if(i >= 0) { - #ifndef TXT_ONLY if(log_config.refine > 0) log_refine(sd, i, 0); - #endif //USE_SQL sd->status.inventory[i].refine = 0; - pc_unequipitem(sd,i,0, BF_NORMAL); + pc_unequipitem(sd,i,3); // ¸˜Bޏ”sƒGƒtƒFƒNƒg‚̃pƒPƒbƒg clif_refine(sd->fd,sd,1,i,sd->status.inventory[i].refine); pc_delitem(sd,i,1,0); @@ -3153,6 +3239,22 @@ int buildin_bonus3(struct script_state *st) return 0; } + +int buildin_bonus4(struct script_state *st) +{ + int type,type2,type3,type4,val; + struct map_session_data *sd; + + type=conv_num(st,& (st->stack->stack_data[st->start+2])); + type2=conv_num(st,& (st->stack->stack_data[st->start+3])); + type3=conv_num(st,& (st->stack->stack_data[st->start+4])); + type4=conv_num(st,& (st->stack->stack_data[st->start+5])); + val=conv_num(st,& (st->stack->stack_data[st->start+6])); + sd=script_rid2sd(st); + pc_bonus4(sd,type,type2,type3,type4,val); + + return 0; +} /*========================================== * ƒXƒLƒ‹Š“¾ *------------------------------------------ @@ -3219,15 +3321,15 @@ int buildin_getskilllv(struct script_state *st) return 0; } /*========================================== - * getgdskilllv(Guild_ID, Skill_ID); - * skill_id = 10000 : GD_APPROVAL - * 10001 : GD_KAFRACONTACT - * 10002 : GD_GUARDIANRESEARCH - * 10003 : GD_GUARDUP - * 10004 : GD_EXTENSION + * getgdskilllv(Guild_ID, Skill_ID); + * skill_id = 10000 : GD_APPROVAL + * 10001 : GD_KAFRACONTACT + * 10002 : GD_GUARDIANRESEARCH + * 10003 : GD_GUARDUP + * 10004 : GD_EXTENSION *------------------------------------------ */ -int buildin_getgdskilllv(struct script_state *st) +int buildin_getgdskilllv(struct script_state *st) { int guild_id=conv_num(st,& (st->stack->stack_data[st->start+2])); int skill_id=conv_num(st,& (st->stack->stack_data[st->start+3])); @@ -3299,6 +3401,46 @@ int buildin_checkoption(struct script_state *st) return 0; } +/*========================================== + * + *------------------------------------------ + */ +int buildin_checkoption1(struct script_state *st) +{ + int type; + struct map_session_data *sd; + + type=conv_num(st,& (st->stack->stack_data[st->start+2])); + sd=script_rid2sd(st); + + if(sd->opt1 & type){ + push_val(st->stack,C_INT,1); + } else { + push_val(st->stack,C_INT,0); + } + + return 0; +} +/*========================================== + * + *------------------------------------------ + */ +int buildin_checkoption2(struct script_state *st) +{ + int type; + struct map_session_data *sd; + + type=conv_num(st,& (st->stack->stack_data[st->start+2])); + sd=script_rid2sd(st); + + if(sd->opt2 & type){ + push_val(st->stack,C_INT,1); + } else { + push_val(st->stack,C_INT,0); + } + + return 0; +} /*========================================== * @@ -3524,11 +3666,11 @@ int buildin_gettimestr(struct script_state *st) fmtstr=conv_str(st,& (st->stack->stack_data[st->start+2])); maxlen=conv_num(st,& (st->stack->stack_data[st->start+3])); - tmpstr=(char *)aCalloc(maxlen+1,sizeof(char)); + tmpstr=(char *)aCallocA(maxlen+1,sizeof(char)); strftime(tmpstr,maxlen,fmtstr,localtime(&now)); tmpstr[maxlen]='\0'; - push_str(st->stack,C_STR,tmpstr); + push_str(st->stack,C_STR,(unsigned char *) tmpstr); return 0; } @@ -3608,11 +3750,11 @@ int buildin_makepet(struct script_state *st) if (pet_id < 0) pet_id = search_petDB_index(id, PET_EGG); if (pet_id >= 0 && sd) { - sd->catch_target_class = pet_db[pet_id].class; + sd->catch_target_class = pet_db[pet_id].class_; intif_create_pet( sd->status.account_id, sd->status.char_id, - pet_db[pet_id].class, mob_db[pet_db[pet_id].class].lv, - pet_db[pet_id].EggID, 0, pet_db[pet_id].intimate, + (short)pet_db[pet_id].class_, (short)mob_db[pet_db[pet_id].class_].lv, + (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate, 100, 0, 1, pet_db[pet_id].jname); } @@ -3638,24 +3780,42 @@ int buildin_getexp(struct script_state *st) } /*========================================== + * Gain guild exp [Celest] + *------------------------------------------ + */ +int buildin_guildgetexp(struct script_state *st) +{ + struct map_session_data *sd = script_rid2sd(st); + int exp; + + exp = conv_num(st,& (st->stack->stack_data[st->start+2])); + if(exp < 0) + return 0; + if(sd && sd->status.guild_id > 0) + guild_getexp (sd, exp); + + return 0; +} + +/*========================================== * ƒ‚ƒ“ƒXƒ^[”¶ *------------------------------------------ */ int buildin_monster(struct script_state *st) { - int class,amount,x,y; + int class_,amount,x,y; char *str,*map,*event=""; map =conv_str(st,& (st->stack->stack_data[st->start+2])); x =conv_num(st,& (st->stack->stack_data[st->start+3])); y =conv_num(st,& (st->stack->stack_data[st->start+4])); str =conv_str(st,& (st->stack->stack_data[st->start+5])); - class=conv_num(st,& (st->stack->stack_data[st->start+6])); + class_=conv_num(st,& (st->stack->stack_data[st->start+6])); amount=conv_num(st,& (st->stack->stack_data[st->start+7])); if( st->end>st->start+8 ) event=conv_str(st,& (st->stack->stack_data[st->start+8])); - mob_once_spawn(map_id2sd(st->rid),map,x,y,str,class,amount,event); + mob_once_spawn(map_id2sd(st->rid),map,x,y,str,class_,amount,event); return 0; } /*========================================== @@ -3664,7 +3824,7 @@ int buildin_monster(struct script_state *st) */ int buildin_areamonster(struct script_state *st) { - int class,amount,x0,y0,x1,y1; + int class_,amount,x0,y0,x1,y1; char *str,*map,*event=""; map =conv_str(st,& (st->stack->stack_data[st->start+2])); @@ -3673,12 +3833,12 @@ int buildin_areamonster(struct script_state *st) x1 =conv_num(st,& (st->stack->stack_data[st->start+5])); y1 =conv_num(st,& (st->stack->stack_data[st->start+6])); str =conv_str(st,& (st->stack->stack_data[st->start+7])); - class=conv_num(st,& (st->stack->stack_data[st->start+8])); + class_=conv_num(st,& (st->stack->stack_data[st->start+8])); amount=conv_num(st,& (st->stack->stack_data[st->start+9])); if( st->end>st->start+10 ) event=conv_str(st,& (st->stack->stack_data[st->start+10])); - mob_once_spawn_area(map_id2sd(st->rid),map,x0,y0,x1,y1,str,class,amount,event); + mob_once_spawn_area(map_id2sd(st->rid),map,x0,y0,x1,y1,str,class_,amount,event); return 0; } /*========================================== @@ -3808,7 +3968,7 @@ int buildin_initnpctimer(struct script_state *st) nd=(struct npc_data *)map_id2bl(st->oid); npc_settimerevent_tick(nd,0); - npc_timerevent_start(nd); + npc_timerevent_start(nd, st->rid); return 0; } /*========================================== @@ -3823,7 +3983,7 @@ int buildin_startnpctimer(struct script_state *st) else nd=(struct npc_data *)map_id2bl(st->oid); - npc_timerevent_start(nd); + npc_timerevent_start(nd, st->rid); return 0; } /*========================================== @@ -3882,6 +4042,46 @@ int buildin_setnpctimer(struct script_state *st) } /*========================================== + * attaches the player rid to the timer [Celest] + *------------------------------------------ + */ +int buildin_attachnpctimer(struct script_state *st) +{ + struct map_session_data *sd; + struct npc_data *nd; + + nd=(struct npc_data *)map_id2bl(st->oid); + if( st->end > st->start+2 ) { + char *name = conv_str(st,& (st->stack->stack_data[st->start+2])); + sd=map_nick2sd(name); + } else { + sd = script_rid2sd(st); + } + + if (sd==NULL) + return 0; + + nd->u.scr.rid = sd->bl.id; + return 0; +} + +/*========================================== + * detaches a player rid from the timer [Celest] + *------------------------------------------ + */ +int buildin_detachnpctimer(struct script_state *st) +{ + struct npc_data *nd; + if( st->end > st->start+2 ) + nd=npc_name2id(conv_str(st,& (st->stack->stack_data[st->start+2]))); + else + nd=(struct npc_data *)map_id2bl(st->oid); + + nd->u.scr.rid = 0; + return 0; +} + +/*========================================== * “V‚̺ƒAƒiƒEƒ“ƒX *------------------------------------------ */ @@ -3971,6 +4171,25 @@ int buildin_getusers(struct script_state *st) return 0; } /*========================================== + * Works like @WHO - displays all online users names in window + *------------------------------------------ + */ +int buildin_getusersname(struct script_state *st) +{ + struct map_session_data *pl_sd = NULL; + int i=0,disp_num=1; + + for (i=0;i<fd_max;i++) + if(session[i] && (pl_sd=(struct map_session_data *) session[i]->session_data) && pl_sd->state.auth){ + if( !(battle_config.hide_GM_session && pc_isGM(pl_sd)) ){ + if((disp_num++)%10==0) + clif_scriptnext(script_rid2sd(st),st->oid); + clif_scriptmes(script_rid2sd(st),st->oid,pl_sd->status.name); + } + } + return 0; +} +/*========================================== * ƒ}ƒbƒvŽw’胆[ƒU[”Š“¾ *------------------------------------------ */ @@ -4146,9 +4365,12 @@ int buildin_sc_start(struct script_state *st) bl = map_id2bl(conv_num(st,& (st->stack->stack_data[st->start+5]))); else bl = map_id2bl(st->rid); - if(bl->type == BL_PC && ((struct map_session_data *)bl)->state.potionpitcher_flag) - bl = map_id2bl(((struct map_session_data *)bl)->skilltarget); - skill_status_change_start(bl,type,val1,0,0,0,tick,0); + + if (bl != 0) { + if(bl->type == BL_PC && ((struct map_session_data *)bl)->state.potionpitcher_flag) + bl = map_id2bl(((struct map_session_data *)bl)->skilltarget); + status_change_start(bl,type,val1,0,0,0,tick,0); + } return 0; } @@ -4171,7 +4393,7 @@ int buildin_sc_start2(struct script_state *st) if(bl->type == BL_PC && ((struct map_session_data *)bl)->state.potionpitcher_flag) bl = map_id2bl(((struct map_session_data *)bl)->skilltarget); if(rand()%10000 < per) - skill_status_change_start(bl,type,val1,0,0,0,tick,0); + status_change_start(bl,type,val1,0,0,0,tick,0); return 0; } @@ -4187,7 +4409,7 @@ int buildin_sc_end(struct script_state *st) bl = map_id2bl(st->rid); if(bl->type == BL_PC && ((struct map_session_data *)bl)->state.potionpitcher_flag) bl = map_id2bl(((struct map_session_data *)bl)->skilltarget); - skill_status_change_end(bl,type,-1); + status_change_end(bl,type,-1); // if(battle_config.etc_log) // printf("sc_end : %d %d\n",st->rid,type); return 0; @@ -4199,8 +4421,7 @@ int buildin_sc_end(struct script_state *st) int buildin_getscrate(struct script_state *st) { struct block_list *bl; - int sc_def=100,sc_def_mdef2,sc_def_vit2,sc_def_int2,sc_def_luk2; - int type,rate,luk; + int sc_def,type,rate; type=conv_num(st,& (st->stack->stack_data[st->start+2])); rate=conv_num(st,& (st->stack->stack_data[st->start+3])); @@ -4209,22 +4430,9 @@ int buildin_getscrate(struct script_state *st) else bl = map_id2bl(st->rid); - luk = battle_get_luk(bl); - sc_def_mdef2=100 - (3 + battle_get_mdef(bl) + luk/3); - sc_def_vit2=100 - (3 + battle_get_vit(bl) + luk/3); - sc_def_int2=100 - (3 + battle_get_int(bl) + luk/3); - sc_def_luk2=100 - (3 + luk); - - if(type==SC_STONE || type==SC_FREEZE) - sc_def=sc_def_mdef2; - else if(type==SC_STAN || type==SC_POISON || type==SC_SILENCE) - sc_def=sc_def_vit2; - else if(type==SC_SLEEP || type==SC_CONFUSION || type==SC_BLIND) - sc_def=sc_def_int2; - else if(type==SC_CURSE) - sc_def=sc_def_luk2; - - rate=rate*sc_def/100; + sc_def = status_get_sc_def(bl,type); + + rate = rate * sc_def / 100; push_val(st->stack,C_INT,rate); return 0; @@ -4347,13 +4555,13 @@ int buildin_changesex(struct script_state *st) { if (sd->status.sex == 0) { sd->status.sex = 1; sd->sex = 1; - if (sd->status.class == 20 || sd->status.class == 4021) - sd->status.class -= 1; + if (sd->status.class_ == 20 || sd->status.class_ == 4021) + sd->status.class_ -= 1; } else if (sd->status.sex == 1) { sd->status.sex = 0; sd->sex = 0; - if(sd->status.class == 19 || sd->status.class == 4020) - sd->status.class += 1; + if(sd->status.class_ == 19 || sd->status.class_ == 4020) + sd->status.class_ += 1; } chrif_char_ask_name(-1, sd->status.name, 5, 0, 0, 0, 0, 0, 0); // type: 5 - changesex chrif_save(sd); @@ -4395,6 +4603,29 @@ int buildin_waitingroom(struct script_state *st) return 0; } /*========================================== + * Works like 'announce' but outputs in the common chat window + *------------------------------------------ + */ +int buildin_globalmes(struct script_state *st) +{ + struct block_list *bl = map_id2bl(st->oid); + struct npc_data *nd = (struct npc_data *)bl; + char *name=NULL,*mes; + + mes=conv_str(st,& (st->stack->stack_data[st->start+2])); // ƒƒbƒZ[ƒW‚̎擾 + if(mes==NULL) return 0; + + if(st->end>st->start+3){ // NPC–¼‚̎擾(123#456) + name=conv_str(st,& (st->stack->stack_data[st->start+3])); + } else { + name=nd->name; + } + + npc_globalmessage(name,mes); // ƒOƒ[ƒoƒ‹ƒƒbƒZ[ƒW‘—M + + return 0; +} +/*========================================== * npcƒ`ƒƒƒbƒgíœ *------------------------------------------ */ @@ -4496,13 +4727,13 @@ int buildin_getwaitingroomstate(struct script_state *st) case 33: val=(cd->users >= cd->trigger); break; case 4: - push_str(st->stack,C_CONSTSTR,cd->title); + push_str(st->stack,C_CONSTSTR,(unsigned char *) cd->title); return 0; case 5: - push_str(st->stack,C_CONSTSTR,cd->pass); + push_str(st->stack,C_CONSTSTR,(unsigned char *) cd->pass); return 0; case 16: - push_str(st->stack,C_CONSTSTR,cd->npc_event); + push_str(st->stack,C_CONSTSTR,(unsigned char *) cd->npc_event); return 0; } push_val(st->stack,C_INT,val); @@ -4534,7 +4765,7 @@ int buildin_warpwaitingpc(struct script_state *st) for(i=0;i<n;i++){ struct map_session_data *sd=cd->usersd[0]; // ƒŠƒXƒg擪‚ÌPC‚ðŽŸX‚ÉB - mapreg_setreg(add_str("$@warpwaitingpc")+(i<<24),sd->bl.id); + mapreg_setreg(add_str((unsigned char *) "$@warpwaitingpc")+(i<<24),sd->bl.id); if(strcmp(str,"Random")==0) pc_randomwarp(sd,3); @@ -4547,7 +4778,7 @@ int buildin_warpwaitingpc(struct script_state *st) }else pc_setpos(sd,str,x,y,0); } - mapreg_setreg(add_str("$@warpwaitingpcnum"),n); + mapreg_setreg(add_str((unsigned char *) "$@warpwaitingpcnum"),n); return 0; } /*========================================== @@ -4790,7 +5021,7 @@ int buildin_pvpon(struct script_state *st) return 0; for(i=0;i<fd_max;i++){ //l”•ªƒ‹[ƒv - if(session[i] && (pl_sd=session[i]->session_data) && pl_sd->state.auth){ + if(session[i] && (pl_sd=(struct map_session_data *) session[i]->session_data) && pl_sd->state.auth){ if(m == pl_sd->bl.m && pl_sd->pvp_timer == -1) { pl_sd->pvp_timer=add_timer(gettick()+200,pc_calc_pvprank_timer,pl_sd->bl.id,0); pl_sd->pvp_rank=0; @@ -4820,7 +5051,7 @@ int buildin_pvpoff(struct script_state *st) return 0; for(i=0;i<fd_max;i++){ //l”•ªƒ‹[ƒv - if(session[i] && (pl_sd=session[i]->session_data) && pl_sd->state.auth){ + if(session[i] && (pl_sd=(struct map_session_data *) session[i]->session_data) && pl_sd->state.auth){ if(m == pl_sd->bl.m) { clif_pvpset(pl_sd,0,0,2); if(pl_sd->pvp_timer != -1) { @@ -4899,7 +5130,7 @@ int buildin_maprespawnguildid_sub(struct block_list *bl,va_list ap) pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,3); // end addition [Valaris] } if(md && flag&4){ - if(md->class < 1285 || md->class > 1288) + if(md->class_ < 1285 || md->class_ > 1288) mob_delete(md); } return 0; @@ -4942,15 +5173,15 @@ int buildin_agitcheck(struct script_state *st) struct map_session_data *sd; int cond; - sd=script_rid2sd(st); cond=conv_num(st,& (st->stack->stack_data[st->start+2])); if(cond == 0) { if (agit_flag==1) push_val(st->stack,C_INT,1); if (agit_flag==0) push_val(st->stack,C_INT,0); } else { - if (agit_flag==1) pc_setreg(sd,add_str("@agit_flag"),1); - if (agit_flag==0) pc_setreg(sd,add_str("@agit_flag"),0); + sd=script_rid2sd(st); + if (agit_flag==1) pc_setreg(sd,add_str((unsigned char *) "@agit_flag"),1); + if (agit_flag==0) pc_setreg(sd,add_str((unsigned char *) "@agit_flag"),0); } return 0; } @@ -4974,16 +5205,16 @@ int buildin_getcastlename(struct script_state *st) for(i=0;i<MAX_GUILDCASTLE;i++){ if( (gc=guild_castle_search(i)) != NULL ){ if(strcmp(mapname,gc->map_name)==0){ - buf=(char *)aCalloc(24,sizeof(char)); + buf=(char *)aCallocA(24,sizeof(char)); strncpy(buf,gc->castle_name,24); break; } } } if(buf) - push_str(st->stack,C_STR,buf); + push_str(st->stack,C_STR,(unsigned char *) buf); else - push_str(st->stack,C_CONSTSTR,""); + push_str(st->stack,C_CONSTSTR,(unsigned char *) ""); return 0; } @@ -5130,9 +5361,9 @@ int buildin_getequipcardcnt(struct script_state *st) return 0; } do{ - if( (sd->status.inventory[i].card[c-1] > 4000) && - (sd->status.inventory[i].card[c-1] < 5000)){ - + if( (sd->status.inventory[i].card[c-1] > 4000 && + sd->status.inventory[i].card[c-1] < 5000) || + itemdb_type(sd->status.inventory[i].card[c-1]) == 6){ // [Celest] push_val(st->stack,C_INT,(c)); return 0; } @@ -5159,8 +5390,9 @@ int buildin_successremovecards(struct script_state *st) return 0; } do{ - if( (sd->status.inventory[i].card[c-1] > 4000) && - (sd->status.inventory[i].card[c-1] < 5000)){ + if( (sd->status.inventory[i].card[c-1] > 4000 && + sd->status.inventory[i].card[c-1] < 5000) || + itemdb_type(sd->status.inventory[i].card[c-1]) == 6){ // [Celest] cardflag = 1; item_tmp.id=0,item_tmp.nameid=sd->status.inventory[i].card[c-1]; @@ -5212,10 +5444,11 @@ int buildin_failedremovecards(struct script_state *st) return 0; } do{ - if(( sd->status.inventory[i].card[c-1] > 4000) && - (sd->status.inventory[i].card[c-1] < 5000)){ - - cardflag = 1; + if( (sd->status.inventory[i].card[c-1] > 4000 && + sd->status.inventory[i].card[c-1] < 5000) || + itemdb_type(sd->status.inventory[i].card[c-1]) == 6){ // [Celest] + + cardflag = 1; if(typefail == 2){ // •‹ï‚̂ݑ¹Ž¸‚È‚çAƒJ[ƒh‚͎󂯎æ‚点‚é item_tmp.id=0,item_tmp.nameid=sd->status.inventory[i].card[c-1]; @@ -5293,9 +5526,9 @@ int buildin_cmdothernpc(struct script_state *st) // Added by RoVeRT int buildin_inittimer(struct script_state *st) // Added by RoVeRT { // struct npc_data *nd=(struct npc_data*)map_id2bl(st->oid); - // nd->lastaction=nd->timer=gettick(); - npc_do_ontimer(st->oid, map_id2sd(st->rid), 1); + + npc_do_ontimer(st->oid, 1); return 0; } @@ -5303,9 +5536,9 @@ int buildin_inittimer(struct script_state *st) // Added by RoVeRT int buildin_stoptimer(struct script_state *st) // Added by RoVeRT { // struct npc_data *nd=(struct npc_data*)map_id2bl(st->oid); - // nd->lastaction=nd->timer=-1; - npc_do_ontimer(st->oid, map_id2sd(st->rid), 0); + + npc_do_ontimer(st->oid, 0); return 0; } @@ -5354,10 +5587,13 @@ int buildin_marriage(struct script_state *st) int buildin_wedding_effect(struct script_state *st) { struct map_session_data *sd=script_rid2sd(st); + struct block_list *bl; - if(sd==NULL) - return 0; - clif_wedding_effect(&sd->bl); + if(sd==NULL) { + bl=map_id2bl(st->oid); + } else + bl=&sd->bl; + clif_wedding_effect(bl); return 0; } int buildin_divorce(struct script_state *st) @@ -5371,6 +5607,56 @@ int buildin_divorce(struct script_state *st) return 0; } +int buildin_ispartneron(struct script_state *st) +{ + struct map_session_data *sd=script_rid2sd(st); + struct map_session_data *p_sd=NULL; + + if(sd==NULL || !pc_ismarried(sd) || + ((p_sd=map_nick2sd(map_charid2nick(sd->status.partner_id))) == NULL)) { + push_val(st->stack,C_INT,0); + return 0; + } + + push_val(st->stack,C_INT,1); + return 0; +} + +int buildin_getpartnerid(struct script_state *st) +{ + struct map_session_data *sd=script_rid2sd(st); + if (sd == NULL) { + push_val(st->stack,C_INT,0); + return 0; + } + + push_val(st->stack,C_INT,sd->status.partner_id); + return 0; +} + +int buildin_warppartner(struct script_state *st) +{ + int x,y; + char *str; + struct map_session_data *sd=script_rid2sd(st); + struct map_session_data *p_sd=NULL; + + if(sd==NULL || !pc_ismarried(sd) || + ((p_sd=map_nick2sd(map_charid2nick(sd->status.partner_id))) == NULL)) { + push_val(st->stack,C_INT,0); + return 0; + } + + str=conv_str(st,& (st->stack->stack_data[st->start+2])); + x=conv_num(st,& (st->stack->stack_data[st->start+3])); + y=conv_num(st,& (st->stack->stack_data[st->start+4])); + + pc_setpos(p_sd,str,x,y,0); + + push_val(st->stack,C_INT,1); + return 0; +} + /*================================================ * Script for Displaying MOB Information [Valaris] *------------------------------------------------ @@ -5379,35 +5665,48 @@ int buildin_strmobinfo(struct script_state *st) { int num=conv_num(st,& (st->stack->stack_data[st->start+2])); - int class=conv_num(st,& (st->stack->stack_data[st->start+3])); + int class_=conv_num(st,& (st->stack->stack_data[st->start+3])); - if(num<=0 || num>=8 || (class>=0 && class<=1000) || class >2000) + if((class_>=0 && class_<=1000) || class_ >2000) return 0; - if(num==1) { - char *buf; - buf=calloc(24, 1); - buf=mob_db[class].name; - push_str(st->stack,C_STR,buf); - return 0; - } - else if(num==2) { - char *buf; - buf=calloc(24, 1); - buf=mob_db[class].jname; - push_str(st->stack,C_STR,buf); - return 0; + switch (num) { + case 1: + { + char *buf; + buf=(char *) aCallocA(24, 1); +// buf=mob_db[class_].name; +// for string assignments you would need to go for c++ [Shinomori] + strcpy(buf,mob_db[class_].name); + push_str(st->stack,C_STR,(unsigned char *) buf); + break; + } + case 2: + { + char *buf; + buf=(char *) aCallocA(24, 1); +// buf=mob_db[class_].jname; +// for string assignments you would need to go for c++ [Shinomori] + strcpy(buf,mob_db[class_].jname); + push_str(st->stack,C_STR,(unsigned char *) buf); + break; + } + case 3: + push_val(st->stack,C_INT,mob_db[class_].lv); + break; + case 4: + push_val(st->stack,C_INT,mob_db[class_].max_hp); + break; + case 5: + push_val(st->stack,C_INT,mob_db[class_].max_sp); + break; + case 6: + push_val(st->stack,C_INT,mob_db[class_].base_exp); + break; + case 7: + push_val(st->stack,C_INT,mob_db[class_].job_exp); + break; } - else if(num==3) - push_val(st->stack,C_INT,mob_db[class].lv); - else if(num==4) - push_val(st->stack,C_INT,mob_db[class].max_hp); - else if(num==5) - push_val(st->stack,C_INT,mob_db[class].max_sp); - else if(num==6) - push_val(st->stack,C_INT,mob_db[class].base_exp); - else if(num==7) - push_val(st->stack,C_INT,mob_db[class].job_exp); return 0; } @@ -5417,20 +5716,20 @@ int buildin_strmobinfo(struct script_state *st) */ int buildin_guardian(struct script_state *st) { - int class=0,amount=1,x=0,y=0,guardian=0; + int class_=0,amount=1,x=0,y=0,guardian=0; char *str,*map,*event=""; map =conv_str(st,& (st->stack->stack_data[st->start+2])); x =conv_num(st,& (st->stack->stack_data[st->start+3])); y =conv_num(st,& (st->stack->stack_data[st->start+4])); str =conv_str(st,& (st->stack->stack_data[st->start+5])); - class=conv_num(st,& (st->stack->stack_data[st->start+6])); + class_=conv_num(st,& (st->stack->stack_data[st->start+6])); amount=conv_num(st,& (st->stack->stack_data[st->start+7])); event=conv_str(st,& (st->stack->stack_data[st->start+8])); if( st->end>st->start+9 ) guardian=conv_num(st,& (st->stack->stack_data[st->start+9])); - mob_spawn_guardian(map_id2sd(st->rid),map,x,y,str,class,amount,event,guardian); + mob_spawn_guardian(map_id2sd(st->rid),map,x,y,str,class_,amount,event,guardian); return 0; } @@ -5471,10 +5770,10 @@ int buildin_getitemname(struct script_state *st) i_data = NULL; i_data = itemdb_search(item_id); - item_name=(char *)aCalloc(24,sizeof(char)); + item_name=(char *)aCallocA(24,sizeof(char)); strncpy(item_name,i_data->jname,23); - push_str(st->stack,C_STR,item_name); + push_str(st->stack,C_STR,(unsigned char *) item_name); return 0; } @@ -5485,12 +5784,12 @@ int buildin_getitemname(struct script_state *st) int buildin_petskillbonus(struct script_state *st) { - int type,val,duration,timer; + int type,val,duration,timer; struct pet_data *pd; - struct map_session_data *sd=script_rid2sd(st); + struct map_session_data *sd=script_rid2sd(st); - if(sd==NULL || sd->pd==NULL) + if(sd==NULL || sd->pd==NULL) return 0; pd=sd->pd; @@ -5503,10 +5802,17 @@ int buildin_petskillbonus(struct script_state *st) duration=conv_num(st,& (st->stack->stack_data[st->start+4])); timer=conv_num(st,& (st->stack->stack_data[st->start+5])); - pd->skillbonusduration=-1; - pd->skillbonustimer=-1; - - pet_skill_bonus(sd,pd,type,val,duration,timer,0); + // initialise bonuses + pd->skillbonustype=type; + pd->skillbonusval=val; + pd->skillduration=duration*1000; + pd->skilltimer=timer*1000; + + if (pd->state.skillbonus == -1) + pd->state.skillbonus=0; // waiting state + + // wait for timer to start + pd->skillbonustimer=add_timer(gettick()+pd->skilltimer,pet_skill_bonus_timer,sd->bl.id,0); return 0; } @@ -5533,7 +5839,7 @@ int buildin_petloot(struct script_state *st) if(!max) return 0; - + pd->loot=1; pd->lootmax=max; @@ -5550,20 +5856,20 @@ int buildin_getinventorylist(struct script_state *st) if(!sd) return 0; for(i=0;i<MAX_INVENTORY;i++){ if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0){ - pc_setreg(sd,add_str("@inventorylist_id")+(j<<24),sd->status.inventory[i].nameid); - pc_setreg(sd,add_str("@inventorylist_amount")+(j<<24),sd->status.inventory[i].amount); - pc_setreg(sd,add_str("@inventorylist_equip")+(j<<24),sd->status.inventory[i].equip); - pc_setreg(sd,add_str("@inventorylist_refine")+(j<<24),sd->status.inventory[i].refine); - pc_setreg(sd,add_str("@inventorylist_identify")+(j<<24),sd->status.inventory[i].identify); - pc_setreg(sd,add_str("@inventorylist_attribute")+(j<<24),sd->status.inventory[i].attribute); - pc_setreg(sd,add_str("@inventorylist_card1")+(j<<24),sd->status.inventory[i].card[0]); - pc_setreg(sd,add_str("@inventorylist_card2")+(j<<24),sd->status.inventory[i].card[1]); - pc_setreg(sd,add_str("@inventorylist_card3")+(j<<24),sd->status.inventory[i].card[2]); - pc_setreg(sd,add_str("@inventorylist_card4")+(j<<24),sd->status.inventory[i].card[3]); + pc_setreg(sd,add_str((unsigned char *) "@inventorylist_id")+(j<<24),sd->status.inventory[i].nameid); + pc_setreg(sd,add_str((unsigned char *) "@inventorylist_amount")+(j<<24),sd->status.inventory[i].amount); + pc_setreg(sd,add_str((unsigned char *) "@inventorylist_equip")+(j<<24),sd->status.inventory[i].equip); + pc_setreg(sd,add_str((unsigned char *) "@inventorylist_refine")+(j<<24),sd->status.inventory[i].refine); + pc_setreg(sd,add_str((unsigned char *) "@inventorylist_identify")+(j<<24),sd->status.inventory[i].identify); + pc_setreg(sd,add_str((unsigned char *) "@inventorylist_attribute")+(j<<24),sd->status.inventory[i].attribute); + pc_setreg(sd,add_str((unsigned char *) "@inventorylist_card1")+(j<<24),sd->status.inventory[i].card[0]); + pc_setreg(sd,add_str((unsigned char *) "@inventorylist_card2")+(j<<24),sd->status.inventory[i].card[1]); + pc_setreg(sd,add_str((unsigned char *) "@inventorylist_card3")+(j<<24),sd->status.inventory[i].card[2]); + pc_setreg(sd,add_str((unsigned char *) "@inventorylist_card4")+(j<<24),sd->status.inventory[i].card[3]); j++; } } - pc_setreg(sd,add_str("@inventorylist_count"),j); + pc_setreg(sd,add_str((unsigned char *) "@inventorylist_count"),j); return 0; } @@ -5574,13 +5880,13 @@ int buildin_getskilllist(struct script_state *st) if(!sd) return 0; for(i=0;i<MAX_SKILL;i++){ if(sd->status.skill[i].id > 0 && sd->status.skill[i].lv > 0){ - pc_setreg(sd,add_str("@skilllist_id")+(j<<24),sd->status.skill[i].id); - pc_setreg(sd,add_str("@skilllist_lv")+(j<<24),sd->status.skill[i].lv); - pc_setreg(sd,add_str("@skilllist_flag")+(j<<24),sd->status.skill[i].flag); + pc_setreg(sd,add_str((unsigned char *) "@skilllist_id")+(j<<24),sd->status.skill[i].id); + pc_setreg(sd,add_str((unsigned char *)"@skilllist_lv")+(j<<24),sd->status.skill[i].lv); + pc_setreg(sd,add_str((unsigned char *)"@skilllist_flag")+(j<<24),sd->status.skill[i].flag); j++; } } - pc_setreg(sd,add_str("@skilllist_count"),j); + pc_setreg(sd,add_str((unsigned char *) "@skilllist_count"),j); return 0; } @@ -5604,14 +5910,14 @@ int buildin_clearitem(struct script_state *st) */ int buildin_classchange(struct script_state *st) { - int class,type; + int _class,type; struct block_list *bl=map_id2bl(st->oid); - + if(bl==NULL) return 0; - class=conv_num(st,& (st->stack->stack_data[st->start+2])); + _class=conv_num(st,& (st->stack->stack_data[st->start+2])); type=conv_num(st,& (st->stack->stack_data[st->start+3])); - clif_class_change(bl,class,type); + clif_class_change(bl,_class,type); return 0; } @@ -5655,6 +5961,24 @@ int buildin_soundeffect(struct script_state *st) } return 0; } + +int buildin_soundeffectall(struct script_state *st) +{ + struct map_session_data *sd=script_rid2sd(st); + char *name; + int type=0; + + name=conv_str(st,& (st->stack->stack_data[st->start+2])); + type=conv_num(st,& (st->stack->stack_data[st->start+3])); + if(sd) + { + if(st->oid) + clif_soundeffectall(map_id2bl(st->oid),name,type); + else + clif_soundeffectall(&sd->bl,name,type); + } + return 0; +} /*========================================== * pet status recovery [Valaris] *------------------------------------------ @@ -5663,9 +5987,9 @@ int buildin_petrecovery(struct script_state *st) { struct pet_data *pd; - struct map_session_data *sd=script_rid2sd(st); + struct map_session_data *sd=script_rid2sd(st); - if(sd==NULL || sd->pd==NULL) + if(sd==NULL || sd->pd==NULL) return 0; pd=sd->pd; @@ -5689,9 +6013,9 @@ int buildin_petheal(struct script_state *st) { struct pet_data *pd; - struct map_session_data *sd=script_rid2sd(st); + struct map_session_data *sd=script_rid2sd(st); - if(sd==NULL || sd->pd==NULL) + if(sd==NULL || sd->pd==NULL) return 0; pd=sd->pd; @@ -5707,7 +6031,7 @@ int buildin_petheal(struct script_state *st) return 0; } - + /*========================================== * pet magnificat [Valaris] *------------------------------------------ @@ -5715,9 +6039,9 @@ int buildin_petheal(struct script_state *st) int buildin_petmag(struct script_state *st) { struct pet_data *pd; - struct map_session_data *sd=script_rid2sd(st); + struct map_session_data *sd=script_rid2sd(st); - if(sd==NULL || sd->pd==NULL) + if(sd==NULL || sd->pd==NULL) return 0; pd=sd->pd; @@ -5742,9 +6066,9 @@ int buildin_petmag(struct script_state *st) int buildin_petskillattack(struct script_state *st) { struct pet_data *pd; - struct map_session_data *sd=script_rid2sd(st); + struct map_session_data *sd=script_rid2sd(st); - if(sd==NULL || sd->pd==NULL) + if(sd==NULL || sd->pd==NULL) return 0; pd=sd->pd; @@ -5753,7 +6077,7 @@ int buildin_petskillattack(struct script_state *st) return 0; pd->skilltype=conv_num(st,& (st->stack->stack_data[st->start+2])); - pd->skillval=conv_num(st,& (st->stack->stack_data[st->start+3])); + pd->skillval=conv_num(st,& (st->stack->stack_data[st->start+3])); pd->skillduration=conv_num(st,& (st->stack->stack_data[st->start+4])); pd->skilltimer=conv_num(st,& (st->stack->stack_data[st->start+5])); @@ -5761,6 +6085,24 @@ int buildin_petskillattack(struct script_state *st) return 0; } + +/*========================================== + * Scripted skill effects [Celest] + *------------------------------------------ + */ +int buildin_skilleffect(struct script_state *st) +{ + struct map_session_data *sd; + + int skillid=conv_num(st,& (st->stack->stack_data[st->start+2])); + int skilllv=conv_num(st,& (st->stack->stack_data[st->start+3])); + sd=script_rid2sd(st); + + clif_skill_nodamage(&sd->bl,&sd->bl,skillid,skilllv,1); + + return 0; +} + /*========================================== * NPC skill effects [Valaris] *------------------------------------------ @@ -5768,9 +6110,9 @@ int buildin_petskillattack(struct script_state *st) int buildin_npcskilleffect(struct script_state *st) { struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); - + int skillid=conv_num(st,& (st->stack->stack_data[st->start+2])); - int skilllv=conv_num(st,& (st->stack->stack_data[st->start+3])); + int skilllv=conv_num(st,& (st->stack->stack_data[st->start+3])); int x=conv_num(st,& (st->stack->stack_data[st->start+4])); int y=conv_num(st,& (st->stack->stack_data[st->start+5])); @@ -5814,15 +6156,15 @@ int buildin_specialeffect2(struct script_state *st) int buildin_nude(struct script_state *st) { - struct map_session_data *sd=script_rid2sd(st); + struct map_session_data *sd=script_rid2sd(st); int i; if(sd==NULL) return 0; - - for(i=0;i<11;i++) + + for(i=0;i<11;i++) if(sd->equip_index[i] >= 0) - pc_unequipitem(sd,sd->equip_index[i],1, BF_NORMAL); + pc_unequipitem(sd,sd->equip_index[i],2); return 0; } @@ -5848,6 +6190,221 @@ int buildin_gmcommand(struct script_state *st) } /*========================================== + * Displays a message for the player only (like system messages like "you got an apple" ) + *------------------------------------------ + */ +int buildin_dispbottom(struct script_state *st) +{ + struct map_session_data *sd=script_rid2sd(st); + char *message; + message=conv_str(st,& (st->stack->stack_data[st->start+2])); + if(sd) + clif_disp_onlyself(sd,message,strlen(message)); + return 0; +} + +/*========================================== + * All The Players Full Recovery + (HP/SP full restore and resurrect if need) + *------------------------------------------ + */ +int buildin_recovery(struct script_state *st) +{ + int i = 0; + for (i = 0; i < fd_max; i++) { + if (session[i]){ + struct map_session_data *sd = (struct map_session_data *) session[i]->session_data; + if (sd && sd->state.auth) { + sd->status.hp = sd->status.max_hp; + sd->status.sp = sd->status.max_sp; + clif_updatestatus(sd, SP_HP); + clif_updatestatus(sd, SP_SP); + if(pc_isdead(sd)){ + pc_setstand(sd); + clif_resurrection(&sd->bl, 1); + } + clif_displaymessage(sd->fd,"You have been recovered!"); + } + } + } + return 0; +} +/*========================================== + * Get your pet info: getpetinfo(n) + * n -> 0:pet_id 1:pet_class 2:pet_name + 3:friendly 4:hungry + *------------------------------------------ + */ +int buildin_getpetinfo(struct script_state *st) +{ + struct map_session_data *sd=script_rid2sd(st); + int type=conv_num(st,& (st->stack->stack_data[st->start+2])); + + if(sd && sd->status.pet_id){ + switch(type){ + case 0: + push_val(st->stack,C_INT,sd->status.pet_id); + break; + case 1: + if(sd->pet.class_) + push_val(st->stack,C_INT,sd->pet.class_); + else + push_val(st->stack,C_INT,0); + break; + case 2: + if(sd->pet.name) + push_str(st->stack,C_STR,(unsigned char *) sd->pet.name); + else + push_val(st->stack,C_INT,0); + break; + case 3: + //if(sd->pet.intimate) + push_val(st->stack,C_INT,sd->pet.intimate); + break; + case 4: + //if(sd->pet.hungry) + push_val(st->stack,C_INT,sd->pet.hungry); + break; + default: + push_val(st->stack,C_INT,0); + break; + } + }else{ + push_val(st->stack,C_INT,0); + } + return 0; +} +/*========================================== + * Shows wether your inventory(and equips) contain + selected card or not. + checkequipedcard(4001); + *------------------------------------------ + */ +int buildin_checkequipedcard(struct script_state *st) +{ + struct map_session_data *sd=script_rid2sd(st); + int n,i,c=0; + c=conv_num(st,& (st->stack->stack_data[st->start+2])); + + if(sd){ + for(i=0;i<MAX_INVENTORY;i++){ + if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount){ + for(n=0;n<4;n++){ + if(sd->status.inventory[i].card[n]==c){ + push_val(st->stack,C_INT,1); + return 0; + } + } + } + } + } + push_val(st->stack,C_INT,0); + return 0; +} + +int buildin_jump_zero(struct script_state *st) { + int sel; + sel=conv_num(st,& (st->stack->stack_data[st->start+2])); + if(!sel) { + int pos; + if( st->stack->stack_data[st->start+3].type!=C_POS ){ + printf("script: jump_zero: not label !\n"); + st->state=END; + return 0; + } + + pos=conv_num(st,& (st->stack->stack_data[st->start+3])); + st->pos=pos; + st->state=GOTO; + // printf("script: jump_zero: jumpto : %d\n",pos); + } else { + // printf("script: jump_zero: fail\n"); + } + return 0; +} + +int buildin_select(struct script_state *st) +{ + char *buf; + int len,i; + struct map_session_data *sd; + + sd=script_rid2sd(st); + + if(sd->state.menu_or_input==0){ + st->state=RERUNLINE; + sd->state.menu_or_input=1; + for(i=st->start+2,len=16;i<st->end;i++){ + conv_str(st,& (st->stack->stack_data[i])); + len+=strlen(st->stack->stack_data[i].u.str)+1; + } + buf=(char *)aCalloc(len+1,sizeof(char)); + buf[0]=0; + for(i=st->start+2,len=0;i<st->end;i++){ + strcat(buf,st->stack->stack_data[i].u.str); + strcat(buf,":"); + } + clif_scriptmenu(script_rid2sd(st),st->oid,buf); + aFree(buf); + } else if(sd->npc_menu==0xff){ // cansel + sd->state.menu_or_input=0; + st->state=END; + } else { + pc_setreg(sd,add_str((unsigned char *) "l15"),sd->npc_menu); + pc_setreg(sd,add_str((unsigned char *) "@menu"),sd->npc_menu); + sd->state.menu_or_input=0; + push_val(st->stack,C_INT,sd->npc_menu); + } + return 0; +} + +/*========================================== + * GetMapMobs + returns mob counts on a set map: + e.g. GetMapMobs("prontera.gat") + use "this" - for player's map + *------------------------------------------ + */ +int buildin_getmapmobs(struct script_state *st) +{ + char *str=NULL; + int m=-1,bx,by,i; + int count=0,c; + struct block_list *bl; + + str=conv_str(st,& (st->stack->stack_data[st->start+2])); + + if(strcmp(str,"this")==0){ + struct map_session_data *sd=script_rid2sd(st); + if(sd) + m=sd->bl.m; + else{ + push_val(st->stack,C_INT,-1); + return 0; + } + }else + m=map_mapname2mapid(str); + + if(m < 0){ + push_val(st->stack,C_INT,-1); + return 0; + } + + for(by=0;by<=(map[m].ys-1)/BLOCK_SIZE;by++){ + for(bx=0;bx<=(map[m].xs-1)/BLOCK_SIZE;bx++){ + bl = map[m].block_mob[bx+by*map[m].bxs]; + c = map[m].block_mob_count[bx+by*map[m].bxs]; + for(i=0;i<c && bl;i++,bl=bl->next){ + if(bl->x>=0 && bl->x<=map[m].xs-1 && bl->y>=0 && bl->y<=map[m].ys-1) + count++; + } + } + } + push_val(st->stack,C_INT,count); + return 0; +} + +/*========================================== * movenpc [MouseJstr] *------------------------------------------ */ @@ -5896,7 +6453,7 @@ int buildin_message(struct script_state *st) * area) [Valaris] *------------------------------------------ */ - + int buildin_npctalk(struct script_state *st) { char *str; @@ -5926,16 +6483,16 @@ int buildin_hasitems(struct script_state *st) { int i; struct map_session_data *sd; - + sd=script_rid2sd(st); - + for(i=0; i<MAX_INVENTORY; i++) { if(sd->status.inventory[i].amount) { push_val(st->stack,C_INT,1); return 0; } } - + push_val(st->stack,C_INT,0); return 0; @@ -6040,14 +6597,14 @@ int buildin_getsavepoint(struct script_state *st) sd=script_rid2sd(st); type=conv_num(st,& (st->stack->stack_data[st->start+2])); - mapname=calloc(24, 1); + mapname=(char *) aCallocA(24, 1); x=sd->status.save_point.x; y=sd->status.save_point.y; strncpy(mapname,sd->status.save_point.map,24); switch(type){ case 0: - push_str(st->stack,C_STR,mapname); + push_str(st->stack,C_STR,(unsigned char *) mapname); break; case 1: push_val(st->stack,C_INT,x); @@ -6109,7 +6666,7 @@ int buildin_getmapxy(struct script_state *st){ //??????????? >>> Possible needly check function parameters on C_STR,C_INT,C_INT <<< ???????????// type=conv_num(st,& (st->stack->stack_data[st->start+5])); - mapname=calloc(24, 1); + mapname=(char *) aCallocA(24, 1); switch (type){ case 0: //Get Character Position @@ -6141,7 +6698,7 @@ int buildin_getmapxy(struct script_state *st){ } x=nd->bl.x; - y=nd->bl.y; + y=nd->bl.y; strncpy(mapname,map[nd->bl.m].name,24); printf(">>>>%s %d %d\n",mapname,x,y); break; @@ -6163,7 +6720,7 @@ int buildin_getmapxy(struct script_state *st){ return 0; } x=pd->bl.x; - y=pd->bl.y; + y=pd->bl.y; strncpy(mapname,map[pd->bl.m].name,24); printf(">>>>%s %d %d\n",mapname,x,y); @@ -6218,6 +6775,260 @@ int buildin_getmapxy(struct script_state *st){ return 0; } +/*===================================================== + * Allows players to use a skill - by Qamera + *----------------------------------------------------- + */ +int buildin_skilluseid (struct script_state *st) +{ + int skid,sklv; + struct map_session_data *sd; + + skid=conv_num(st,& (st->stack->stack_data[st->start+2])); + sklv=conv_num(st,& (st->stack->stack_data[st->start+3])); + sd=script_rid2sd(st); + skill_use_id(sd,sd->status.account_id,skid,sklv); + + return 0; +} + +/*===================================================== + * Allows players to use a skill on a position [Celest] + *----------------------------------------------------- + */ +int buildin_skillusepos(struct script_state *st) +{ + int skid,sklv,x,y; + struct map_session_data *sd; + + skid=conv_num(st,& (st->stack->stack_data[st->start+2])); + sklv=conv_num(st,& (st->stack->stack_data[st->start+3])); + x=conv_num(st,& (st->stack->stack_data[st->start+4])); + y=conv_num(st,& (st->stack->stack_data[st->start+5])); + + sd=script_rid2sd(st); + skill_use_pos(sd,x,y,skid,sklv); + + return 0; +} + +/*========================================== + * Allows player to write NPC logs (i.e. Bank NPC, etc) [Lupus] + *------------------------------------------ + */ +int buildin_logmes(struct script_state *st) +{ + if (log_config.npc <= 0 ) return 0; + conv_str(st,& (st->stack->stack_data[st->start+2])); + log_npc(script_rid2sd(st),st->stack->stack_data[st->start+2].u.str); + return 0; +} + +int buildin_summon(struct script_state *st) +{ + int _class, id; + char *str,*event=""; + struct map_session_data *sd; + struct mob_data *md; + + sd=script_rid2sd(st); + if (sd) { + int tick = gettick(); + str =conv_str(st,& (st->stack->stack_data[st->start+2])); + _class=conv_num(st,& (st->stack->stack_data[st->start+3])); + if( st->end>st->start+4 ) + event=conv_str(st,& (st->stack->stack_data[st->start+4])); + + id=mob_once_spawn(sd, "this", 0, 0, str,_class,1,event); + if((md=(struct mob_data *)map_id2bl(id))){ + md->master_id=sd->bl.id; + md->state.special_mob_ai=1; + md->mode=mob_db[md->class_].mode|0x04; + md->deletetimer=add_timer(tick+60000,mob_timer_delete,id,0); + clif_misceffect2(&md->bl,344); + } + clif_skill_poseffect(&sd->bl,AM_CALLHOMUN,1,sd->bl.x,sd->bl.y,tick); + } + + return 0; +} + +int buildin_isnight(struct script_state *st) +{ + push_val(st->stack,C_INT, (night_flag == 1)); + return 0; +} + +int buildin_isday(struct script_state *st) +{ + push_val(st->stack,C_INT, (night_flag == 0)); + return 0; +} + +/*================================================ + * Check whether another item/card has been + * equipped - used for 2/15's cards patch [celest] + *------------------------------------------------ + */ +int buildin_isequipped(struct script_state *st) +{ + struct map_session_data *sd; + int i, j, k, id = 1; + int ret = -1; + + sd = script_rid2sd(st); + + for (i=0; id!=0; i++) { + int flag = 0; + + FETCH (i+2, id) else id = 0; + if (id <= 0) + continue; + + for (j=0; j<10; j++) { + int index, type; + index = sd->equip_index[j]; + if(index < 0) continue; + if(j == 9 && sd->equip_index[8] == index) continue; + if(j == 5 && sd->equip_index[4] == index) continue; + if(j == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index)) continue; + type = itemdb_type(id); + + if(sd->inventory_data[index]) { + if (type == 4 || type == 5) { + if (sd->inventory_data[index]->nameid == id) + flag = 1; + } else if (type == 6) { + for(k=0; k<sd->inventory_data[index]->slot; k++) { + if (sd->status.inventory[index].card[0]!=0x00ff && + sd->status.inventory[index].card[0]!=0x00fe && + sd->status.inventory[index].card[0]!=(short)0xff00 && + sd->status.inventory[index].card[k] == id) { + flag = 1; + break; + } + } + } + if (flag) break; + } + } + if (ret == -1) + ret = flag; + else + ret &= flag; + if (!ret) break; + } + + push_val(st->stack,C_INT,ret); + return 0; +} + +/*================================================ + * Check how many items/cards in the list are + * equipped - used for 2/15's cards patch [celest] + *------------------------------------------------ + */ +int buildin_isequippedcnt(struct script_state *st) +{ + struct map_session_data *sd; + int i, j, k, id = 1; + int ret = 0; + + sd = script_rid2sd(st); + + for (i=0; id!=0; i++) { + FETCH (i+2, id) else id = 0; + if (id <= 0) + continue; + + for (j=0; j<10; j++) { + int index, type; + index = sd->equip_index[j]; + if(index < 0) continue; + if(j == 9 && sd->equip_index[8] == index) continue; + if(j == 5 && sd->equip_index[4] == index) continue; + if(j == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index)) continue; + type = itemdb_type(id); + + if(sd->inventory_data[index]) { + if (type == 4 || type == 5) { + if (sd->inventory_data[index]->nameid == id) + ret++; //[Lupus] + } else if (type == 6) { + for(k=0; k<sd->inventory_data[index]->slot; k++) { + if (sd->status.inventory[index].card[0]!=0x00ff && + sd->status.inventory[index].card[0]!=0x00fe && + sd->status.inventory[index].card[0]!=(short)0xff00 && + sd->status.inventory[index].card[k] == id) { + ret++; //[Lupus] + } + } + } + } + } + } + + push_val(st->stack,C_INT,ret); + return 0; +} + +/*================================================ + * Check how many given inserted cards in the CURRENT + * weapon - used for 2/15's cards patch [Lupus] + *------------------------------------------------ + */ +int buildin_cardscnt(struct script_state *st) +{ + struct map_session_data *sd; + int i, k, id = 1; + int ret = 0; + int index, type; + + sd = script_rid2sd(st); + + for (i=0; id!=0; i++) { + FETCH (i+2, id) else id = 0; + if (id <= 0) + continue; + + index = current_equip_item_index; //we get CURRENT WEAPON inventory index from status.c [Lupus] + if(index < 0) continue; + + type = itemdb_type(id); + + if(sd->inventory_data[index]) { + if (type == 4 || type == 5) { + if (sd->inventory_data[index]->nameid == id) + ret++; + } else if (type == 6) { + for(k=0; k<sd->inventory_data[index]->slot; k++) { + if (sd->status.inventory[index].card[0]!=0x00ff && + sd->status.inventory[index].card[0]!=0x00fe && + sd->status.inventory[index].card[0]!=(short)0xff00 && + sd->status.inventory[index].card[k] == id) { + ret++; + } + } + } + } + } + push_val(st->stack,C_INT,ret); +// push_val(st->stack,C_INT,current_equip_item_index); + return 0; +} + +/*======================================================= + * Returns the refined number of the current item, or an + * item with inventory index specified + *------------------------------------------------------- + */ +int buildin_getrefine(struct script_state *st) +{ + struct map_session_data *sd; + if ((sd = script_rid2sd(st))!= NULL) + push_val(st->stack, C_INT, sd->status.inventory[current_equip_item_index].refine); + return 0; +} // // ŽÀs•”main @@ -6309,14 +7120,14 @@ void op_add(struct script_state* st) st->stack->stack_data[st->stack->sp-1].u.num += st->stack->stack_data[st->stack->sp].u.num; } else { // ss‚Ì—\’è char *buf; - buf=(char *)aCalloc(strlen(st->stack->stack_data[st->stack->sp-1].u.str)+ + buf=(char *)aCallocA(strlen(st->stack->stack_data[st->stack->sp-1].u.str)+ strlen(st->stack->stack_data[st->stack->sp].u.str)+1,sizeof(char)); strcpy(buf,st->stack->stack_data[st->stack->sp-1].u.str); strcat(buf,st->stack->stack_data[st->stack->sp].u.str); if(st->stack->stack_data[st->stack->sp-1].type==C_STR) - free(st->stack->stack_data[st->stack->sp-1].u.str); + aFree(st->stack->stack_data[st->stack->sp-1].u.str); if(st->stack->stack_data[st->stack->sp].type==C_STR) - free(st->stack->stack_data[st->stack->sp].u.str); + aFree(st->stack->stack_data[st->stack->sp].u.str); st->stack->stack_data[st->stack->sp-1].type=C_STR; st->stack->stack_data[st->stack->sp-1].u.str=buf; } @@ -6358,8 +7169,8 @@ void op_2str(struct script_state *st,int op,int sp1,int sp2) push_val(st->stack,C_INT,a); - if(st->stack->stack_data[sp1].type==C_STR) free(s1); - if(st->stack->stack_data[sp2].type==C_STR) free(s2); + if(st->stack->stack_data[sp1].type==C_STR) aFree(s1); + if(st->stack->stack_data[sp2].type==C_STR) aFree(s2); } /*========================================== * “ñ€‰‰ŽZŽq(”’l) @@ -6373,7 +7184,11 @@ void op_2num(struct script_state *st,int op,int i1,int i2) break; case C_MUL: { + #ifndef _MSC_VER long long res = i1 * i2; + #else + __int64 res = i1 * i2; + #endif if (res > 2147483647 ) i1 = 2147483647; else @@ -6572,7 +7387,7 @@ int run_func(struct script_state *st) * ƒXƒNƒŠƒvƒg‚ÌŽÀsƒƒCƒ“•”•ª *------------------------------------------ */ -int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_state *st,unsigned char *rootscript) +int run_script_main(char *script,int pos,int rid,int oid,struct script_state *st,char *rootscript) { int c,rerun_pos; int cmdcount=script_config.check_cmdcount; @@ -6584,7 +7399,7 @@ int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_ rerun_pos=st->pos; for(st->state=0;st->state==0;){ - switch(c=get_com(script,&st->pos)){ + switch(c= get_com((unsigned char *) script,&st->pos)){ case C_EOL: if(stack->sp!=st->defsp){ if(battle_config.error_log) @@ -6594,7 +7409,7 @@ int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_ rerun_pos=st->pos; break; case C_INT: - push_val(stack,C_INT,get_num(script,&st->pos)); + push_val(stack,C_INT,get_num((unsigned char *) script,&st->pos)); break; case C_POS: case C_NAME: @@ -6605,7 +7420,7 @@ int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_ push_val(stack,c,0); break; case C_STR: - push_str(stack,C_CONSTSTR,script+st->pos); + push_str(stack,C_CONSTSTR,(unsigned char *) (script+st->pos)); while(script[st->pos++]); break; case C_FUNC: @@ -6689,7 +7504,7 @@ int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_ struct map_session_data *sd=map_id2sd(st->rid); if(sd/* && sd->npc_stackbuf==NULL*/){ if( sd->npc_stackbuf ) - free( sd->npc_stackbuf ); + aFree( sd->npc_stackbuf ); sd->npc_stackbuf = (char *)aCalloc(sizeof(stack->stack_data[0])*stack->sp_max,sizeof(char)); memcpy(sd->npc_stackbuf, stack->stack_data, sizeof(stack->stack_data[0]) * stack->sp_max); sd->npc_stack = stack->sp; @@ -6706,24 +7521,24 @@ int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_ * ƒXƒNƒŠƒvƒg‚ÌŽÀs *------------------------------------------ */ -int run_script(unsigned char *script,int pos,int rid,int oid) +int run_script(char *script,int pos,int rid,int oid) { struct script_stack stack; struct script_state st; struct map_session_data *sd=map_id2sd(rid); - unsigned char *rootscript=script; + char *rootscript=script; if(script==NULL || pos<0) return -1; - if(sd && sd->npc_stackbuf && sd->npc_scriptroot==(char*)rootscript){ + if(sd && sd->npc_stackbuf && sd->npc_scriptroot==rootscript){ // ‘O‰ñ‚̃Xƒ^ƒbƒN‚𕜋A script=sd->npc_script; stack.sp=sd->npc_stack; stack.sp_max=sd->npc_stackmax; stack.stack_data=(struct script_data *)aCalloc(stack.sp_max,sizeof(stack.stack_data[0])); memcpy(stack.stack_data,sd->npc_stackbuf,sizeof(stack.stack_data[0])*stack.sp_max); - free(sd->npc_stackbuf); + aFree(sd->npc_stackbuf); sd->npc_stackbuf=NULL; }else{ // ƒXƒ^ƒbƒN‰Šú‰» @@ -6737,7 +7552,7 @@ int run_script(unsigned char *script,int pos,int rid,int oid) st.oid=oid; run_script_main(script,pos,rid,oid,&st,rootscript); - free(stack.stack_data); + aFree(stack.stack_data); stack.stack_data=NULL; return st.pos; } @@ -6765,15 +7580,15 @@ int mapreg_setregstr(int num,const char *str) { char *p; - if( (p=numdb_search(mapregstr_db,num))!=NULL ) - free(p); + if( (p=(char *) numdb_search(mapregstr_db,num))!=NULL ) + aFree(p); if( str==NULL || *str==0 ){ numdb_erase(mapregstr_db,num); mapreg_dirty=1; return 0; } - p=(char *)aCalloc(strlen(str)+1, sizeof(char)); + p=(char *)aCallocA(strlen(str)+1, sizeof(char)); strcpy(p,str); numdb_insert(mapregstr_db,num,p); mapreg_dirty=1; @@ -6803,16 +7618,16 @@ static int script_load_mapreg() printf("%s: %s broken data !\n",mapreg_txt,buf1); continue; } - p=(char *)aCalloc(strlen(buf2) + 1,sizeof(char)); + p=(char *)aCallocA(strlen(buf2) + 1,sizeof(char)); strcpy(p,buf2); - s=add_str(buf1); + s= add_str((unsigned char *) buf1); numdb_insert(mapregstr_db,(i<<24)|s,p); }else{ if( sscanf(line+n,"%d",&v)!=1 ){ printf("%s: %s broken data !\n",mapreg_txt,buf1); continue; } - s=add_str(buf1); + s= add_str((unsigned char *) buf1); numdb_insert(mapreg_db,(i<<24)|s,v); } } @@ -6871,7 +7686,7 @@ static int script_autosave_mapreg(int tid,unsigned int tick,int id,int data) } /*========================================== - * + * *------------------------------------------ */ static int set_posword(char *p) @@ -6903,8 +7718,16 @@ int script_config_read(char *cfgName) script_config.warn_cmd_no_comma=1; script_config.warn_func_mismatch_paramnum=1; script_config.warn_cmd_mismatch_paramnum=1; - script_config.check_cmdcount=8192; - script_config.check_gotocount=512; + script_config.check_cmdcount=65535; + script_config.check_gotocount=2048; + + script_config.die_event_name = (char *)aCallocA(24,sizeof(char)); + script_config.kill_event_name = (char *)aCallocA(24,sizeof(char)); + script_config.login_event_name = (char *)aCallocA(24,sizeof(char)); + script_config.logout_event_name = (char *)aCallocA(24,sizeof(char)); + + script_config.event_script_type = 0; + script_config.event_requires_trigger = 1; fp=fopen(cfgName,"r"); if(fp==NULL){ @@ -6920,7 +7743,43 @@ int script_config_read(char *cfgName) if(strcmpi(w1,"refine_posword")==0) { set_posword(w2); } - if(strcmpi(w1,"import")==0){ + else if(strcmpi(w1,"warn_func_no_comma")==0) { + script_config.warn_func_no_comma = battle_config_switch(w2); + } + else if(strcmpi(w1,"warn_cmd_no_comma")==0) { + script_config.warn_cmd_no_comma = battle_config_switch(w2); + } + else if(strcmpi(w1,"warn_func_mismatch_paramnum")==0) { + script_config.warn_func_mismatch_paramnum = battle_config_switch(w2); + } + else if(strcmpi(w1,"warn_cmd_mismatch_paramnum")==0) { + script_config.warn_cmd_mismatch_paramnum = battle_config_switch(w2); + } + else if(strcmpi(w1,"check_cmdcount")==0) { + script_config.check_cmdcount = battle_config_switch(w2); + } + else if(strcmpi(w1,"check_gotocount")==0) { + script_config.check_gotocount = battle_config_switch(w2); + } + else if(strcmpi(w1,"event_script_type")==0) { + script_config.event_script_type = battle_config_switch(w2); + } + else if(strcmpi(w1,"die_event_name")==0) { + strcpy(script_config.die_event_name, w2); + } + else if(strcmpi(w1,"kill_event_name")==0) { + strcpy(script_config.kill_event_name, w2); + } + else if(strcmpi(w1,"login_event_name")==0) { + strcpy(script_config.login_event_name, w2); + } + else if(strcmpi(w1,"logout_event_name")==0) { + strcpy(script_config.logout_event_name, w2); + } + else if(strcmpi(w1,"require_set_trigger")==0) { + script_config.event_requires_trigger = battle_config_switch(w2); + } + else if(strcmpi(w1,"import")==0){ script_config_read(w2); } } @@ -6939,7 +7798,7 @@ static int mapreg_db_final(void *key,void *data,va_list ap) } static int mapregstr_db_final(void *key,void *data,va_list ap) { - free(data); + aFree(data); return 0; } static int scriptlabel_db_final(void *key,void *data,va_list ap) @@ -6948,16 +7807,16 @@ static int scriptlabel_db_final(void *key,void *data,va_list ap) } static int userfunc_db_final(void *key,void *data,va_list ap) { - free(key); - free(data); + aFree(key); + aFree(data); return 0; } int do_final_script() { if(mapreg_dirty>=0) script_save_mapreg(); - if(script_buf) - free(script_buf); +// if(script_buf) +// aFree(script_buf); if(mapreg_db) numdb_final(mapreg_db,mapreg_db_final); @@ -6968,10 +7827,19 @@ int do_final_script() if(userfunc_db) strdb_final(userfunc_db,userfunc_db_final); - if (str_data) - free(str_data); - if (str_buf) - free(str_buf); + if (str_data) + aFree(str_data); + if (str_buf) + aFree(str_buf); + + if (script_config.die_event_name) + aFree(script_config.die_event_name); + if (script_config.kill_event_name) + aFree(script_config.kill_event_name); + if (script_config.login_event_name) + aFree(script_config.login_event_name); + if (script_config.logout_event_name) + aFree(script_config.logout_event_name); return 0; } diff --git a/src/map/script.h b/src/map/script.h index b50c46693..b30201a67 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -2,6 +2,22 @@ #ifndef _SCRIPT_H_ #define _SCRIPT_H_ +extern struct Script_Config { + int warn_func_no_comma; + int warn_cmd_no_comma; + int warn_func_mismatch_paramnum; + int warn_cmd_mismatch_paramnum; + int check_cmdcount; + int check_gotocount; + + int event_script_type; + char* die_event_name; + char* kill_event_name; + char* login_event_name; + char* logout_event_name; + int event_requires_trigger; +} script_config; + struct script_data { int type; union { @@ -23,8 +39,12 @@ struct script_state { int defsp,new_pos,new_defsp; }; -unsigned char * parse_script(unsigned char *,int); -int run_script(unsigned char *,int,int,int); +char * parse_script(unsigned char *,int); +int run_script(char *,int,int,int); + +int set_var(struct map_session_data *sd, char *name, void *val); +int conv_num(struct script_state *st,struct script_data *data); +char* conv_str(struct script_state *st,struct script_data *data); struct dbt* script_get_label_db(); struct dbt* script_get_userfunc_db(); diff --git a/src/map/skill.c b/src/map/skill.c index dc708c906..c53a7a9d6 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1,4 +1,4 @@ -// $Id: skill.c,v 1.8 2004/11/26 7:12:23 PM Celestia Exp $ +// $Id: skill.c,v 1.8 2004/02/27 5:34:51 PM Celestia $ /* ƒXƒLƒ‹?ŒW */ #include <stdio.h> @@ -14,6 +14,7 @@ #include "map.h" #include "clif.h" #include "pc.h" +#include "status.h" #include "pet.h" #include "mob.h" #include "battle.h" @@ -24,245 +25,16 @@ #include "log.h" #include "chrif.h" #include "guild.h" +#include "showmsg.h" +#include "grfio.h" #ifdef MEMWATCH #include "memwatch.h" #endif #define SKILLUNITTIMER_INVERVAL 100 - #define STATE_BLIND 0x10 - -/* ƒXƒLƒ‹”Ô?„ƒXƒe?ƒ^ƒXˆÙí”Ô??Š·ƒe?ƒuƒ‹ */ -int SkillStatusChangeTable[]={ /* skill.h‚Ìenum‚ÌSC_***‚Æ‚ ‚킹‚邱‚Æ */ -/* 0- */ - -1,-1,-1,-1,-1,-1, - SC_PROVOKE, /* ƒvƒƒ{ƒbƒN */ - -1, 1,-1, -/* 10- */ - SC_SIGHT, /* ƒTƒCƒg */ - -1,-1,-1,-1, - SC_FREEZE, /* ƒtƒƒXƒgƒ_ƒCƒo? */ - SC_STONE, /* ƒXƒg?ƒ“ƒJ?ƒX */ - -1,-1,-1, -/* 20- */ - -1,-1,-1,-1, - SC_RUWACH, /* ƒ‹ƒAƒt */ - -1,-1,-1,-1, - SC_INCREASEAGI, /* ‘¬“x?‰Á */ -/* 30- */ - SC_DECREASEAGI, /* ‘¬“xŒ¸ */ - -1, - SC_SIGNUMCRUCIS, /* ƒVƒOƒiƒ€ƒNƒ‹ƒVƒX */ - SC_ANGELUS, /* ƒGƒ“ƒWƒFƒ‰ƒX */ - SC_BLESSING, /* ƒuƒŒƒbƒVƒ“ƒO */ - -1,-1,-1,-1,-1, -/* 40- */ - -1,-1,-1,-1,-1, - SC_CONCENTRATE, /* W’†—ÍŒüã */ - -1,-1,-1,-1, -/* 50- */ - -1, - SC_HIDING, /* ƒnƒCƒfƒBƒ“ƒO */ - -1,-1,-1,-1,-1,-1,-1,-1, -/* 60- */ - SC_TWOHANDQUICKEN, /* 2HQ */ - SC_AUTOCOUNTER, - -1,-1,-1,-1, - SC_IMPOSITIO, /* ƒCƒ“ƒ|ƒVƒeƒBƒIƒ}ƒkƒX */ - SC_SUFFRAGIUM, /* ƒTƒtƒ‰ƒMƒEƒ€ */ - SC_ASPERSIO, /* ƒAƒXƒyƒ‹ƒVƒI */ - SC_BENEDICTIO, /* ¹?~•Ÿ */ -/* 70- */ - -1, - SC_SLOWPOISON, - -1, - SC_KYRIE, /* ƒLƒŠƒGƒGƒŒƒCƒ\ƒ“ */ - SC_MAGNIFICAT, /* ƒ}ƒOƒjƒtƒBƒJ?ƒg */ - SC_GLORIA, /* ƒOƒƒŠƒA */ - SC_DIVINA, /* ƒŒƒbƒNƒXƒfƒBƒr?ƒi */ - -1, - SC_AETERNA, /* ƒŒƒbƒNƒXƒG?ƒeƒ‹ƒi */ - -1, -/* 80- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -/* 90- */ - -1,-1, - SC_QUAGMIRE, /* ƒNƒ@ƒOƒ}ƒCƒA */ - -1,-1,-1,-1,-1,-1,-1, -/* 100- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -/* 110- */ - -1, - SC_ADRENALINE, /* ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… */ - SC_WEAPONPERFECTION,/* ƒEƒFƒ|ƒ“ƒp?ƒtƒFƒNƒVƒ‡ƒ“ */ - SC_OVERTHRUST, /* ƒI?ƒo?ƒgƒ‰ƒXƒg */ - SC_MAXIMIZEPOWER, /* ƒ}ƒLƒVƒ}ƒCƒYƒpƒ? */ - -1,-1,-1,-1,-1, -/* 120- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -/* 130- */ - -1,-1,-1,-1,-1, - SC_CLOAKING, /* ƒNƒ?ƒLƒ“ƒO */ - SC_STAN, /* ƒ\ƒjƒbƒNƒuƒ? */ - -1, - SC_ENCPOISON, /* ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“ */ - SC_POISONREACT, /* ƒ|ƒCƒYƒ“ƒŠƒAƒNƒg */ -/* 140- */ - SC_POISON, /* ƒxƒmƒ€ƒ_ƒXƒg */ - SC_SPLASHER, /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ? */ - -1, - SC_TRICKDEAD, /* Ž€‚ñ‚¾‚Ó‚è */ - -1,-1,-1,-1,-1,-1, -/* 150- */ - -1,-1,-1,-1,-1, - SC_LOUD, /* ƒ‰ƒEƒhƒ{ƒCƒX */ - -1, - SC_ENERGYCOAT, /* ƒGƒiƒW?ƒR?ƒg */ - -1,-1, -/* 160- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1, - SC_SELFDESTRUCTION, - -1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1, - SC_KEEPING, - -1,-1, - SC_BARRIER, - -1,-1, - SC_HALLUCINATION, - -1,-1, -/* 210- */ - -1,-1,-1,-1,-1, - SC_STRIPWEAPON, - SC_STRIPSHIELD, - SC_STRIPARMOR, - SC_STRIPHELM, - -1, -/* 220- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -/* 230- */ - -1,-1,-1,-1, - SC_CP_WEAPON, - SC_CP_SHIELD, - SC_CP_ARMOR, - SC_CP_HELM, - -1,-1, -/* 240- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1, - SC_AUTOGUARD, -/* 250- */ - -1,-1, - SC_REFLECTSHIELD, - -1,-1, - SC_DEVOTION, - SC_PROVIDENCE, - SC_DEFENDER, - SC_SPEARSQUICKEN, - -1, -/* 260- */ - -1,-1,-1,-1,-1,-1,-1,-1, - SC_STEELBODY, - SC_BLADESTOP_WAIT, -/* 270- */ - SC_EXPLOSIONSPIRITS, - SC_EXTREMITYFIST, - -1,-1,-1,-1, - SC_MAGICROD, - -1,-1,-1, -/* 280- */ - SC_FLAMELAUNCHER, - SC_FROSTWEAPON, - SC_LIGHTNINGLOADER, - SC_SEISMICWEAPON, - -1, - SC_VOLCANO, - SC_DELUGE, - SC_VIOLENTGALE, - SC_LANDPROTECTOR, - -1, -/* 290- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -/* 300- */ - -1,-1,-1,-1,-1,-1, - SC_LULLABY, - SC_RICHMANKIM, - SC_ETERNALCHAOS, - SC_DRUMBATTLE, -/* 310- */ - SC_NIBELUNGEN, - SC_ROKISWEIL, - SC_INTOABYSS, - SC_SIEGFRIED, - -1,-1,-1, - SC_DISSONANCE, - -1, - SC_WHISTLE, -/* 320- */ - SC_ASSNCROS, - SC_POEMBRAGI, - SC_APPLEIDUN, - -1,-1, - SC_UGLYDANCE, - -1, - SC_HUMMING, - SC_DONTFORGETME, - SC_FORTUNE, -/* 330- */ - SC_SERVICE4U, - SC_SELFDESTRUCTION, - -1,-1,-1,-1,-1,-1,-1,-1, -/* 340- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -/* 350- */ - -1,-1,-1,-1,-1, - SC_AURABLADE, - SC_PARRYING, - SC_CONCENTRATION, - SC_TENSIONRELAX, - SC_BERSERK, -/* 360- */ - SC_BERSERK, - SC_ASSUMPTIO, - SC_BASILICA, - -1,-1,-1, - SC_MAGICPOWER, - -1,-1, - SC_GOSPEL, -/* 370- */ - -1,-1,-1,-1,-1,-1,-1,-1, - - SC_EDP, - - -1, -/* 380- */ - SC_TRUESIGHT, - -1,-1, - SC_WINDWALK, - SC_MELTDOWN, - -1,-1, - SC_CARTBOOST, - -1, - SC_CHASEWALK, -/* 390- */ - SC_REJECTSWORD, - -1,-1,-1,-1,-1, - SC_MARIONETTE, - -1, - SC_HEADCRUSH, - SC_JOINTBEAT, -/* 400 */ - -1,-1, - SC_MINDBREAKER, - SC_MEMORIZE, - SC_FOGWALL, - SC_SPIDERWEB, - -1,-1,-1,-1, -/* 410- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -}; +#define swap(x,y) { int t; t = x; x = y; y = t; } const struct skill_name_db skill_names[] = { { AC_CHARGEARROW, "CHARGEARROW", "Charge_Arrow" } , @@ -398,6 +170,10 @@ const struct skill_name_db skill_names[] = { { DC_SERVICEFORYOU, "SERVICEFORYOU", "Prostitute" } , { DC_THROWARROW, "THROWARROW", "Throw_Arrow" } , { DC_UGLYDANCE, "UGLYDANCE", "Ugly_Dance" } , + { GD_BATTLEORDER, "BATTLEORDER", "Battle_Orders" } , + { GD_REGENERATION, "REGENERATION", "Regeneration" } , + { GD_RESTORE, "RESTORE", "Restore" } , + { GD_EMERGENCYCALL, "EMERGENCYCALL", "Emergency_Call" } , { HP_ASSUMPTIO, "ASSUMPTIO", "Assumptio" } , { HP_BASILICA, "BASILICA", "Basilica" } , { HP_MEDITATIO, "MEDITATIO", "Meditation" } , @@ -698,9 +474,9 @@ const struct skill_name_db skill_names[] = { { TK_SPTIME, "SPTIME", "SP Time" } , { TK_STORMKICK, "STORMKICK", "Storm Kick" } , { TK_TURNKICK, "TURNKICK", "Turn Kick" } , - { WE_BABY, "BABY", "Adopt_Baby" } , - { WE_CALLBABY, "CALLBABY", "Call_Baby" } , - { WE_CALLPARENT, "CALLPARENT", "Call_Parent" } , + { WE_BABY, "BABY", "I Love Mama and Fafa" } , + { WE_CALLBABY, "CALLBABY", "Come With Me, Baby" } , + { WE_CALLPARENT, "CALLPARENT", "I Miss My Parents" } , { WE_CALLPARTNER, "CALLPARTNER", "I Want to See You" } , { WE_FEMALE, "FEMALE", "I Only Look Up to You" } , { WE_MALE, "MALE", "I Will Protect You" } , @@ -724,7 +500,7 @@ const struct skill_name_db skill_names[] = { { WZ_STORMGUST, "STORMGUST", "Storm_Gust" } , { WZ_VERMILION, "VERMILION", "Lord_of_Vermilion" } , { WZ_WATERBALL, "WATERBALL", "Water_Ball" } , - { 0, 0, 0 } + { 0, 0, 0 } }; static const int dirx[8]={0,-1,-1,-1,0,1,1,1}; @@ -744,94 +520,49 @@ struct skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB]; /* ƒAƒuƒ‰ƒJƒ_ƒuƒ‰?“®ƒXƒLƒ‹ƒf?ƒ^ƒx?ƒX */ struct skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB]; -int skill_get_hit( int id ){ - if (id >= 10000 && id < 10015) id -= 9500; - return skill_db[id].hit; -} -int skill_get_inf( int id ){ - return (id < 500) ? skill_db[id].inf : guild_skill_get_inf(id); -} -int skill_get_pl( int id ){ - if (id >= 10000 && id < 10015) id-= 9500; - return skill_db[id].pl; -} -int skill_get_nk( int id ){ - if (id >= 10000 && id < 10015) id-= 9500; - return skill_db[id].nk; -} -int skill_get_max( int id ){ - return (id < 500) ? skill_db[id].max : guild_skill_get_max(id); -} -int skill_get_range( int id , int lv ){ - if (lv <= 0) return 0; - return (id < 500) ? skill_db[id].range[lv-1] : guild_skill_get_range(id); -} -int skill_get_hp( int id ,int lv ){ - if (id >= 10000 && id < 10015) id-= 9500; - return (lv <= 0) ? 0: skill_db[id].hp[lv-1]; -} -int skill_get_sp( int id ,int lv ){ - if (id >= 10000 && id < 10015) id-= 9500; - //if (lv <= 0) return 0; - //return (id < 500) ? skill_db[id].sp[lv-1] : guild_skill_get_sp(id, lv); - return (lv <= 0) ? 0: skill_db[id].sp[lv-1]; -} -int skill_get_zeny( int id ,int lv ){ - if (id >= 10000 && id < 10015) id-= 9500; - return (lv <= 0) ? 0:skill_db[id].zeny[lv-1]; -} -int skill_get_num( int id ,int lv ){ - if (id >= 10000 && id < 10015) id-= 9500; - return (lv <= 0) ? 0:skill_db[id].num[lv-1]; -} -int skill_get_cast( int id ,int lv ){ - if (id >= 10000 && id < 10015) id-= 9500; - return (lv <= 0) ? 0:skill_db[id].cast[lv-1]; -} -int skill_get_delay( int id ,int lv ){ - if (id >= 10000 && id < 10015) id-= 9500; - return (lv <= 0) ? 0:skill_db[id].delay[lv-1]; -} -int skill_get_time( int id ,int lv ){ - if (id >= 10000 && id < 10015) id-= 9500; - return (lv <= 0) ? 0:skill_db[id].upkeep_time[lv-1]; -} -int skill_get_time2( int id ,int lv ){ - if (id >= 10000 && id < 10015) id-= 9500; - return (lv <= 0) ? 0:skill_db[id].upkeep_time2[lv-1]; -} -int skill_get_castdef( int id ){ - if (id >= 10000 && id < 10015) id-= 9500; - return skill_db[id].cast_def_rate; -} -int skill_get_weapontype( int id ){ - if (id >= 10000 && id < 10015) id-= 9500; - return skill_db[id].weapon; -} -int skill_get_inf2( int id ){ - if (id >= 10000 && id < 10015) id-= 9500; - return skill_db[id].inf2; -} -int skill_get_castcancel( int id ){ - if (id >= 10000 && id < 10015) id-= 9500; - return skill_db[id].maxcount; -} -int skill_get_maxcount( int id ){ - if (id >= 10000 && id < 10015) id-= 9500; - return skill_db[id].maxcount; -} -int skill_get_blewcount( int id ,int lv ){ - if (id >= 10000 && id < 10015) id-= 9500; - return (lv <= 0) ? 0:skill_db[id].blewcount[lv-1]; -} -int skill_get_mhp( int id ,int lv ){ - if (id >= 10000 && id < 10015) id-= 9500; - return (lv <= 0) ? 0:skill_db[id].mhp[lv-1]; -} -int skill_get_castnodex( int id ,int lv ){ - if (id >= 10000 && id < 10015) id-= 9500; - return (lv <= 0) ? 0:skill_db[id].castnodex[lv-1]; -} +// macros to check for out of bounds errors [celest] +// i: Skill ID, l: Skill Level, var: Value to return after checking +// for values that don't require level just put a one (putting 0 will trigger return 0; instead +// for values that might need to use a different function just skill_chk would suffice. +#define skill_chk(i, l) \ + if (i >= 10000 && i < 10015) {i -= 9500;} \ + if (i < 1 || i > MAX_SKILL_DB) {return 0;} \ + if (l <= 0 || l > MAX_SKILL_LEVEL) {return 0;} +#define skill_get(var, i, l) \ + { skill_chk(i, l); return var; } + +// Skill DB +int skill_get_hit( int id ){ skill_get (skill_db[id].hit, id, 1); } +int skill_get_inf( int id ){ skill_chk (id, 1); return (id < 500) ? skill_db[id].inf : guild_skill_get_inf(id); } +int skill_get_pl( int id ){ skill_get (skill_db[id].pl, id, 1); } +int skill_get_nk( int id ){ skill_get (skill_db[id].nk, id, 1); } +int skill_get_max( int id ){ skill_chk (id, 1); return (id < 500) ? skill_db[id].max : guild_skill_get_max(id); } +int skill_get_range( int id , int lv ){ skill_chk (id, lv); return (id < 500) ? skill_db[id].range[lv-1] : guild_skill_get_range(id); } +int skill_get_hp( int id ,int lv ){ skill_get (skill_db[id].hp[lv-1], id, lv); } +int skill_get_sp( int id ,int lv ){ skill_get (skill_db[id].sp[lv-1], id, lv); } +int skill_get_zeny( int id ,int lv ){ skill_get (skill_db[id].zeny[lv-1], id, lv); } +int skill_get_num( int id ,int lv ){ skill_get (skill_db[id].num[lv-1], id, lv); } +int skill_get_cast( int id ,int lv ){ skill_get (skill_db[id].cast[lv-1], id, lv); } +int skill_get_delay( int id ,int lv ){ skill_get (skill_db[id].delay[lv-1], id, lv); } +int skill_get_time( int id ,int lv ){ skill_get (skill_db[id].upkeep_time[lv-1], id, lv); } +int skill_get_time2( int id ,int lv ){ skill_get (skill_db[id].upkeep_time2[lv-1], id, lv); } +int skill_get_castdef( int id ){ skill_get (skill_db[id].cast_def_rate, id, 1); } +int skill_get_weapontype( int id ){ skill_get (skill_db[id].weapon, id, 1); } +int skill_get_inf2( int id ){ skill_get (skill_db[id].inf2, id, 1); } +int skill_get_castcancel( int id ){ skill_get (skill_db[id].castcancel, id, 1); } +int skill_get_maxcount( int id ){ skill_get (skill_db[id].maxcount, id, 1); } +int skill_get_blewcount( int id ,int lv ){ skill_get (skill_db[id].blewcount[lv-1], id, lv); } +int skill_get_mhp( int id ,int lv ){ skill_get (skill_db[id].mhp[lv-1], id, lv); } +int skill_get_castnodex( int id ,int lv ){ skill_get (skill_db[id].castnodex[lv-1], id, lv); } +int skill_get_delaynodex( int id ,int lv ){ skill_get (skill_db[id].delaynodex[lv-1], id, lv); } +int skill_get_nocast ( int id ){ skill_get (skill_db[id].nocast, id, 1); } +int skill_get_unit_id ( int id, int flag ){ skill_get (skill_db[id].unit_id[flag], id, 1); } +int skill_get_unit_layout_type( int id ,int lv ){ skill_get (skill_db[id].unit_layout_type[lv-1], id, lv); } +int skill_get_unit_interval( int id ){ skill_get (skill_db[id].unit_interval, id, 1); } +int skill_get_unit_range( int id ){ skill_get (skill_db[id].unit_range, id, 1); } +int skill_get_unit_target( int id ){ skill_get (skill_db[id].unit_target, id, 1); } +int skill_get_unit_flag( int id ){ skill_get (skill_db[id].unit_flag, id, 1); } + int skill_tree_get_max(int id, int b_class){ struct pc_base_job s_class = pc_calc_base_job(b_class); int i, skillid; @@ -845,42 +576,64 @@ int skill_tree_get_max(int id, int b_class){ int skill_check_condition( struct map_session_data *sd,int type); int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag ); int skill_frostjoke_scream(struct block_list *bl,va_list ap); -int skill_status_change_timer_sub(struct block_list *bl, va_list ap ); +int status_change_timer_sub(struct block_list *bl, va_list ap ); int skill_attack_area(struct block_list *bl,va_list ap); -int skill_abra_dataset(int skilllv); int skill_clear_element_field(struct block_list *bl); int skill_landprotector(struct block_list *bl, va_list ap ); int skill_trap_splash(struct block_list *bl, va_list ap ); int skill_count_target(struct block_list *bl, va_list ap ); +struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,struct skill_unit_group *sg,int tick); +int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int tick); +int skill_unit_effect(struct block_list *bl,va_list ap); + +int enchant_eff[5] = { 10, 14, 17, 19, 20 }; +int deluge_eff[5] = { 5, 9, 12, 14, 15 }; // [MouseJstr] - skill ok to cast? and when? -int skillnotok(int skillid, struct map_session_data *sd) { - if (sd == 0) - return 0; - if (pc_isGM(sd) >= 20) - return 0; // gm's can do anything damn thing they want +int skillnotok(int skillid, struct map_session_data *sd) +{ + nullpo_retr (1, sd); + //if (sd == 0) + //return 0; + //return 1; + // I think it was meant to be "no skills allowed when not a valid sd" + + if (!(skillid >= 10000 && skillid < 10015)) + if ((skillid > MAX_SKILL) || (skillid < 0)) + return 1; + + { + int i = skillid; + if (i >= 10000 && i < 10015) + i -= 9500; + if (sd->blockskill[i] > 0) + return 1; + } + + if (pc_isGM(sd) >= 20) + return 0; // gm's can do anything damn thing they want // Check skill restrictions [Celest] - if(!map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.gvg && skill_db[skillid].nocast & 1) + if(!map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.gvg && skill_get_nocast (skillid) & 1) return 1; - if(map[sd->bl.m].flag.pvp && skill_db[skillid].nocast & 2) + if(map[sd->bl.m].flag.pvp && skill_get_nocast (skillid) & 2) return 1; - if(map[sd->bl.m].flag.gvg && skill_db[skillid].nocast & 4) + if(map[sd->bl.m].flag.gvg && skill_get_nocast (skillid) & 4) return 1; - if (agit_flag && skill_db[skillid].nocast & 8) + if (agit_flag && skill_get_nocast (skillid) & 8) return 1; - if (battle_config.pk_mode && !map[sd->bl.m].flag.nopvp && skill_db[skillid].nocast & 16) + if (battle_config.pk_mode && !map[sd->bl.m].flag.nopvp && skill_get_nocast (skillid) & 16) return 1; - - switch (skillid) { - case AL_WARP: - case AL_TELEPORT: - case MC_VENDING: - case MC_IDENTIFY: - return 0; // always allowed - default: - return(map[sd->bl.m].flag.noskill); - } + + switch (skillid) { + case AL_WARP: + case AL_TELEPORT: + case MC_VENDING: + case MC_IDENTIFY: + return 0; // always allowed + default: + return (map[sd->bl.m].flag.noskill); + } } @@ -888,105 +641,58 @@ static int distance(int x0,int y0,int x1,int y1) { int dx,dy; - dx=abs(x0-x1); - dy=abs(y0-y1); - return dx>dy ? dx : dy; + dx = abs(x0 - x1); + dy = abs(y0 - y1); + return dx > dy ? dx : dy; } -/* ƒXƒLƒ‹ƒ†ƒjƒbƒgID‚ð•Ô‚·i‚±‚ê‚àƒf?ƒ^ƒx?ƒX‚É“ü‚ꂽ‚¢‚Èj */ -int skill_get_unit_id(int id,int flag) -{ +/* ƒXƒLƒ‹ƒ†ƒjƒbƒg‚Ì”z’uî•ñ‚ð•Ô‚· */ +struct skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT]; +int firewall_unit_pos; +int icewall_unit_pos; - switch(id){ - case MG_SAFETYWALL: return 0x7e; /* ƒZƒCƒtƒeƒBƒEƒH?ƒ‹ */ - case MG_FIREWALL: return 0x7f; /* ƒtƒ@ƒCƒA?ƒEƒH?ƒ‹ */ - case AL_WARP: return (flag==0)?0x81:0x80; /* ƒ?ƒvƒ|?ƒ^ƒ‹ */ - case PR_BENEDICTIO: return 0x82; /* ¹?~•Ÿ */ - case PR_SANCTUARY: return 0x83; /* ƒTƒ“ƒNƒ`ƒ…ƒAƒŠ */ - case PR_MAGNUS: return 0x84; /* ƒ}ƒOƒkƒXƒGƒNƒ\ƒVƒYƒ€ */ - case AL_PNEUMA: return 0x85; /* ƒjƒ…?ƒ} */ - case MG_THUNDERSTORM: return 0x86; /* ƒTƒ“ƒ_?ƒXƒg?ƒ€ */ - case WZ_HEAVENDRIVE: return 0x86; /* ƒwƒ”ƒ“ƒYƒhƒ‰ƒCƒu */ - case WZ_SIGHTRASHER: return 0x86; /* ƒTƒCƒgƒ‰ƒbƒVƒƒ? */ - case WZ_METEOR: return 0x86; /* ƒƒeƒIƒXƒg?ƒ€ */ - case WZ_VERMILION: return 0x86; /* ƒ?ƒhƒIƒuƒ”ƒ@?ƒ~ƒŠƒIƒ“ */ - case WZ_FROSTNOVA: return 0x86; /* ƒtƒƒXƒgƒmƒ”ƒ@ */ - case WZ_STORMGUST: return 0x86; /* ƒXƒg?ƒ€ƒKƒXƒg(‚Æ‚è‚ ‚¦‚¸LoV‚Æ“¯‚¶‚Å?—) */ - case CR_GRANDCROSS: return 0x86; /* ƒOƒ‰ƒ“ƒhƒNƒƒX */ - case WZ_FIREPILLAR: return (flag==0)?0x87:0x88; /* ƒtƒ@ƒCƒA?ƒsƒ‰? */ - case HT_TALKIEBOX: return 0x99; /* ƒg?ƒL?ƒ{ƒbƒNƒX */ - case WZ_ICEWALL: return 0x8d; /* ƒAƒCƒXƒEƒH?ƒ‹ */ - case WZ_QUAGMIRE: return 0x8e; /* ƒNƒ@ƒOƒ}ƒCƒA */ - case HT_BLASTMINE: return 0x8f; /* ƒuƒ‰ƒXƒgƒ}ƒCƒ“ */ - case HT_SKIDTRAP: return 0x90; /* ƒXƒLƒbƒhƒgƒ‰ƒbƒv */ - case HT_ANKLESNARE: return 0x91; /* ƒAƒ“ƒNƒ‹ƒXƒlƒA */ - case AS_VENOMDUST: return 0x92; /* ƒxƒmƒ€ƒ_ƒXƒg */ - case HT_LANDMINE: return 0x93; /* ƒ‰ƒ“ƒhƒ}ƒCƒ“ */ - case HT_SHOCKWAVE: return 0x94; /* ƒVƒ‡ƒbƒNƒEƒF?ƒuƒgƒ‰ƒbƒv */ - case HT_SANDMAN: return 0x95; /* ƒTƒ“ƒhƒ}ƒ“ */ - case HT_FLASHER: return 0x96; /* ƒtƒ‰ƒbƒVƒƒ? */ - case HT_FREEZINGTRAP: return 0x97; /* ƒtƒŠ?ƒWƒ“ƒOƒgƒ‰ƒbƒv */ - case HT_CLAYMORETRAP: return 0x98; /* ƒNƒŒƒCƒ‚ƒA?ƒgƒ‰ƒbƒv */ - case SA_VOLCANO: return 0x9a; /* ƒ{ƒ‹ƒP?ƒm */ - case SA_DELUGE: return 0x9b; /* ƒfƒŠƒ…?ƒW */ - case SA_VIOLENTGALE: return 0x9c; /* ƒoƒCƒIƒŒƒ“ƒgƒQƒCƒ‹ */ - case SA_LANDPROTECTOR: return 0x9d; /* ƒ‰ƒ“ƒhƒvƒƒeƒNƒ^? */ - case BD_LULLABY: return 0x9e; /* ŽqŽç‰Ì */ - case BD_RICHMANKIM: return 0x9f; /* ƒjƒˆƒ‹ƒh‚̉ƒ */ - case BD_ETERNALCHAOS: return 0xa0; /* ‰i‰“‚̬“× */ - case BD_DRUMBATTLEFIELD:return 0xa1; /* ?‘¾ŒÛ‚Ì‹¿‚« */ - case BD_RINGNIBELUNGEN: return 0xa2; /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ - case BD_ROKISWEIL: return 0xa3; /* ƒƒL‚Ì‹©‚Ñ */ - case BD_INTOABYSS: return 0xa4; /* [•£‚Ì’†‚É */ - case BD_SIEGFRIED: return 0xa5; /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ - case BA_DISSONANCE: return 0xa6; /* •s‹¦˜a‰¹ */ - case BA_WHISTLE: return 0xa7; /* Œû“J */ - case BA_ASSASSINCROSS: return 0xa8; /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX */ - case BA_POEMBRAGI: return 0xa9; /* ƒuƒ‰ƒM‚ÌŽ */ - case BA_APPLEIDUN: return 0xaa; /* ƒCƒhƒDƒ“‚Ì—ÑŒç */ - case DC_UGLYDANCE: return 0xab; /* Ž©•ªŸŽè‚ȃ_ƒ“ƒX */ - case DC_HUMMING: return 0xac; /* ƒnƒ~ƒ“ƒO */ - case DC_DONTFORGETME: return 0xad; /* Ž„‚ð–Y‚ê‚È‚¢‚Åc */ - case DC_FORTUNEKISS: return 0xae; /* K‰^‚̃LƒX */ - case DC_SERVICEFORYOU: return 0xaf; /* ƒT?ƒrƒXƒtƒH?ƒ†? */ - case RG_GRAFFITI: return 0xb0; /* ƒOƒ‰ƒtƒBƒeƒB */ - case AM_DEMONSTRATION: return 0xb1; /* ƒfƒ‚ƒ“ƒXƒgƒŒ?ƒVƒ‡ƒ“ */ - case WE_CALLPARTNER: return 0xb2; /* ‚ ‚È‚½‚Ɉ§‚¢‚½‚¢ */ - case PA_GOSPEL: return 0xb3; /* ƒSƒXƒyƒ‹ */ - case HP_BASILICA: return 0xb4; /* ƒoƒWƒŠƒJ */ - case CG_MOONLIT: return 0xb5; - case PF_FOGWALL: return 0xb6; /* ƒtƒHƒOƒEƒH?ƒ‹ */ - case PF_SPIDERWEB: return 0xb7; /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ - // temporary unit ID's [Celest] - case GD_LEADERSHIP: return 0xc1; - case GD_GLORYWOUNDS: return 0xc2; - case GD_SOULCOLD: return 0xc3; - case GD_HAWKEYES: return 0xc4; - } - return 0; - /* - 0x89,0x8a,0x8b •\ަ–³‚µ - 0x9a ‰Š?«‚̉r¥‚Ý‚½‚¢‚ȃGƒtƒFƒNƒg - 0x9b …?«‚̉r¥‚Ý‚½‚¢‚ȃGƒtƒFƒNƒg - 0x9c •—?«‚̉r¥‚Ý‚½‚¢‚ȃGƒtƒFƒNƒg - 0x9d ”’‚¢¬‚³‚ȃGƒtƒFƒNƒg - 0xb1 Alchemist Demonstration - 0xb2 = Pink Warp Portal - 0xb3 = Gospel For Paladin - 0xb4 = Basilica - 0xb5 = Empty - 0xb6 = Fog Wall for Professor - 0xb7 = Spider Web for Professor - 0xb8 = Empty - 0xb9 = - */ +struct skill_unit_layout *skill_get_unit_layout (int skillid, int skilllv, struct block_list *src, int x, int y) +{ + int pos = skill_get_unit_layout_type(skillid,skilllv); + int dir; + + if (pos != -1) + return &skill_unit_layout[pos]; + + if (src->x == x && src->y == y) + dir = 2; + else + dir = map_calc_dir(src,x,y); + + if (skillid == MG_FIREWALL) + return &skill_unit_layout [firewall_unit_pos + dir]; + else if (skillid == WZ_ICEWALL) + return &skill_unit_layout [icewall_unit_pos + dir]; + + printf("Unknown unit layout for skill %d, %d\n",skillid,skilllv); + return &skill_unit_layout[0]; } +// 0x89,0x8a,0x8b •\ަ–³‚µ +// 0x9a ‰Š?«‚̉r¥‚Ý‚½‚¢‚ȃGƒtƒFƒNƒg +// 0x9b …?«‚̉r¥‚Ý‚½‚¢‚ȃGƒtƒFƒNƒg +// 0x9c •—?«‚̉r¥‚Ý‚½‚¢‚ȃGƒtƒFƒNƒg +// 0x9d ”’‚¢¬‚³‚ȃGƒtƒFƒNƒg +// 0xb1 Alchemist Demonstration +// 0xb2 = Pink Warp Portal +// 0xb3 = Gospel For Paladin +// 0xb4 = Basilica +// 0xb5 = Empty +// 0xb6 = Fog Wall for Professor +// 0xb7 = Spider Web for Professor +// 0xb8 = Empty +// 0xb9 = + /*========================================== * ƒXƒLƒ‹’ljÁ?‰Ê *------------------------------------------ */ -int skill_additional_effect( struct block_list* src, struct block_list *bl,int skillid,int skilllv,int attack_type,unsigned int tick) +int skill_additional_effect (struct block_list* src, struct block_list *bl, int skillid, int skilllv, int attack_type, unsigned int tick) { /* MOB’ljÁ?‰ÊƒXƒLƒ‹—p */ const int sc[]={ @@ -1006,7 +712,7 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s struct pet_data *pd=NULL; int skill,skill2; - int rate,luk; + int rate; int sc_def_mdef,sc_def_vit,sc_def_int,sc_def_luk; int sc_def_mdef2,sc_def_vit2,sc_def_int2,sc_def_luk2; @@ -1014,102 +720,83 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s nullpo_retr(0, src); nullpo_retr(0, bl); - //if(skilllv <= 0) return 0; + if(skillid < 0) + { // remove the debug print when this case is finished + printf("skill_additional_effect: skillid=%i\ncall: %p %p %i %i %i %i",skillid, + src, bl,skillid,skilllv,attack_type,tick); + return 0; + } if(skillid > 0 && skilllv <= 0) return 0; // don't forget auto attacks! - celest - if(src->type==BL_PC){ - nullpo_retr(0, sd=(struct map_session_data *)src); - }else if(src->type==BL_MOB){ - nullpo_retr(0, md=(struct mob_data *)src); //–¢Žg—pH - }else if(src->type==BL_PET){ - nullpo_retr(0, pd=(struct pet_data *)src); // [Valaris] + if (src->type == BL_PC){ + nullpo_retr(0, sd = (struct map_session_data *)src); + } else if (src->type == BL_MOB){ + nullpo_retr(0, md = (struct mob_data *)src); //–¢Žg—pH + } else if (src->type == BL_PET){ + nullpo_retr(0, pd = (struct pet_data *)src); // [Valaris] + } + + if(bl->type == BL_PC) { + nullpo_retr(0, dstsd=(struct map_session_data *)bl); + } else if(bl->type == BL_MOB) { + nullpo_retr(0, dstmd=(struct mob_data *)bl); //–¢Žg—pH } //?ۂ̑ϫ - luk = battle_get_luk(bl); - sc_def_mdef=100 - (3 + battle_get_mdef(bl) + luk/3); - sc_def_vit=100 - (3 + battle_get_vit(bl) + luk/3); - sc_def_int=100 - (3 + battle_get_int(bl) + luk/3); - sc_def_luk=100 - (3 + luk); + sc_def_mdef = status_get_sc_def_mdef(bl); + sc_def_vit = status_get_sc_def_vit(bl); + sc_def_int = status_get_sc_def_int(bl); + sc_def_luk = status_get_sc_def_luk(bl); + //Ž©•ª‚̑ϫ - luk = battle_get_luk(src); - sc_def_mdef2=100 - (3 + battle_get_mdef(src) + luk/3); - sc_def_vit2=100 - (3 + battle_get_vit(src) + luk/3); - sc_def_int2=100 - (3 + battle_get_int(src) + luk/3); - sc_def_luk2=100 - (3 + luk); - if(bl->type==BL_PC) - dstsd=(struct map_session_data *)bl; - else if(bl->type==BL_MOB){ - dstmd=(struct mob_data *)bl; //–¢Žg—pH - if(sc_def_mdef<50) - sc_def_mdef=50; - if(sc_def_vit<50) - sc_def_vit=50; - if(sc_def_int<50) - sc_def_int=50; - if(sc_def_luk<50) - sc_def_luk=50; - } - if(sc_def_mdef<0) - sc_def_mdef=0; - if(sc_def_vit<0) - sc_def_vit=0; - if(sc_def_int<0) - sc_def_int=0; + sc_def_mdef2 = status_get_sc_def_mdef(src); + sc_def_vit2 = status_get_sc_def_vit(src); + sc_def_int2 = status_get_sc_def_int(src); + sc_def_luk2 = status_get_sc_def_luk(src); switch(skillid){ case 0: /* ’ÊíU? */ /* Ž©“®‘é */ - if( sd && pc_isfalcon(sd) && sd->status.weapon == 11 && (skill=pc_checkskill(sd,HT_BLITZBEAT))>0 && - rand()%1000 <= sd->paramc[5]*10/3+1 ) { - int lv=(sd->status.job_level+9)/10; - skill_castend_damage_id(src,bl,HT_BLITZBEAT,(skill<lv)?skill:lv,tick,0xf00000); - } - // ƒXƒiƒbƒ`ƒƒ? - if(sd && sd->status.weapon != 11 && (skill=pc_checkskill(sd,RG_SNATCHER)) > 0) - if((skill*15 + 55) + (skill2 = pc_checkskill(sd,TF_STEAL))*10 > rand()%1000) { + if(sd) { + struct status_change *sc_data = status_get_sc_data(bl); + if (pc_isfalcon(sd) && sd->status.weapon == 11 && (skill=pc_checkskill(sd,HT_BLITZBEAT))>0 && + rand()%1000 <= sd->paramc[5]*10/3+1 ) { + int lv=(sd->status.job_level+9)/10; + skill_castend_damage_id(src,bl,HT_BLITZBEAT,(skill<lv)?skill:lv,tick,0xf00000); + } + // ƒXƒiƒbƒ`ƒƒ? + if(sd->status.weapon != 11 && (skill=pc_checkskill(sd,RG_SNATCHER)) > 0 && + (skill*15 + 55) + (skill2 = pc_checkskill(sd,TF_STEAL))*10 > rand()%1000) { if(pc_steal_item(sd,bl)) clif_skill_nodamage(src,bl,TF_STEAL,skill2,1); else if (battle_config.display_snatcher_skill_fail) - clif_skill_fail(sd,skillid,0,0); // it's annoying! =p [Celest] - } - // ƒGƒ“ƒ`ƒƒƒ“ƒgƒfƒbƒgƒŠ?ƒ|ƒCƒYƒ“(–Ò“Å?‰Ê) - if (sd && sd->sc_data[SC_EDP].timer != -1 && rand() % 10000 < sd->sc_data[SC_EDP].val2 * sc_def_vit) { - int mhp = battle_get_max_hp(bl); - int hp = battle_get_hp(bl); - int lvl = sd->sc_data[SC_EDP].val1; - int diff; - // MHP‚Ì1/4ˆÈ‰º‚ɂ͂Ȃç‚È‚¢ - if(hp > mhp>>2) { - if(bl->type == BL_PC) { - diff = mhp*10/100; - if (hp - diff < mhp>>2) - diff = hp - (mhp>>2); - pc_heal((struct map_session_data *)bl, -hp, 0); - } else if(bl->type == BL_MOB) { - struct mob_data *md = (struct mob_data *)bl; - hp -= mhp*15/100; - if (hp > mhp>>2) - md->hp = hp; - else - md->hp = mhp>>2; - } + clif_skill_fail(sd,skillid,0,0); + } + // enchant poison has a chance of poisoning enemy + if (sd->sc_data[SC_ENCPOISON].timer != -1 && sc_data && sc_data[SC_POISON].timer == -1 && + rand() % 100 < sd->sc_data[SC_ENCPOISON].val1 * sc_def_vit / 100) { + status_change_start(bl,SC_POISON,sd->sc_data[SC_ENCPOISON].val1, + 0,0,0,skill_get_time2(AS_ENCHANTPOISON,sd->sc_data[SC_ENCPOISON].val1),0); } - skill_status_change_start(bl,SC_DPOISON,lvl,0,0,0,skill_get_time2(ASC_EDP,lvl),0); + // ƒGƒ“ƒ`ƒƒƒ“ƒgƒfƒbƒgƒŠ?ƒ|ƒCƒYƒ“(–Ò“Å?‰Ê) + if (sd->sc_data[SC_EDP].timer != -1 && sc_data && sc_data[SC_DPOISON].timer == -1 && + rand() % 100 < sd->sc_data[SC_EDP].val2 * sc_def_vit / 100) + status_change_start(bl,SC_DPOISON,sd->sc_data[SC_EDP].val1, + 0,0,0,skill_get_time2(ASC_EDP,sd->sc_data[SC_EDP].val1),0); } break; case SM_BASH: /* ƒoƒbƒVƒ…i‹}ŠU?j */ if( sd && (skill=pc_checkskill(sd,SM_FATALBLOW))>0 ){ if( rand()%100 < 6*(skilllv-5)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(SM_FATALBLOW,skilllv),0); + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(SM_FATALBLOW,skilllv),0); } break; case TF_POISON: /* ƒCƒ“ƒxƒiƒ€ */ case AS_SPLASHER: /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ? */ if(rand()%100< (2*skilllv+10)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_POISON,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_POISON,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); else{ if(sd && skillid==TF_POISON) clif_skill_fail(sd,skillid,0,0); @@ -1118,122 +805,140 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s case AS_SONICBLOW: /* ƒ\ƒjƒbƒNƒuƒ? */ if( rand()%100 < (2*skilllv+10)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + break; + + case AS_GRIMTOOTH: + if (bl->type == BL_MOB) { + struct status_change *sc_data = status_get_sc_data(bl); + if (sc_data && sc_data[SC_SLOWDOWN].timer == -1) + status_change_start(bl,SC_SLOWDOWN,0,0,0,0,1000,0); + } break; case HT_FREEZINGTRAP: /* ƒtƒŠ?ƒWƒ“ƒOƒgƒ‰ƒbƒv */ rate=skilllv*3+35; if(rand()%100 < rate*sc_def_mdef/100) - skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case MG_FROSTDIVER: /* ƒtƒƒXƒgƒ_ƒCƒo? */ case WZ_FROSTNOVA: /* ƒtƒƒXƒgƒmƒ”ƒ@ */ - rate=(skilllv*3+35)*sc_def_mdef/100-(battle_get_int(bl)+battle_get_luk(bl))/15; - rate=rate<=5?5:rate; - if(rand()%100 < rate) - skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - else if(sd && skillid==MG_FROSTDIVER) - clif_skill_fail(sd,skillid,0,0); + { + struct status_change *sc_data = status_get_sc_data(bl); + rate = (skilllv*3+35)*sc_def_mdef/100-(status_get_int(bl)+status_get_luk(bl))/15; + if (rate <= 5) + rate = 5; + if(sc_data && sc_data[SC_FREEZE].timer == -1 && rand()%100 < rate) + status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv)*(1-sc_def_mdef/100),0); + else if (sd && skillid == MG_FROSTDIVER) + clif_skill_fail(sd,skillid,0,0); + } break; case WZ_STORMGUST: /* ƒXƒg?ƒ€ƒKƒXƒg */ { - struct status_change *sc_data = battle_get_sc_data(bl); + struct status_change *sc_data = status_get_sc_data(bl); if(sc_data) { sc_data[SC_FREEZE].val3++; if(sc_data[SC_FREEZE].val3 >= 3) - skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); } } break; case HT_LANDMINE: /* ƒ‰ƒ“ƒhƒ}ƒCƒ“ */ if( rand()%100 < (5*skilllv+30)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case HT_SHOCKWAVE: /* ƒVƒ‡ƒbƒNƒEƒF?ƒuƒgƒ‰ƒbƒv */ if(map[bl->m].flag.pvp && dstsd){ dstsd->status.sp -= dstsd->status.sp*(5+15*skilllv)/100; - pc_calcstatus(dstsd,0); + status_calc_pc(dstsd,0); } break; case HT_SANDMAN: /* ƒTƒ“ƒhƒ}ƒ“ */ if( rand()%100 < (5*skilllv+30)*sc_def_int/100 ) - skill_status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case TF_SPRINKLESAND: /* »‚Ü‚« */ if( rand()%100 < 20*sc_def_int/100 ) - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case TF_THROWSTONE: /* Î“Š‚° */ if( rand()%100 < 7*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case CR_HOLYCROSS: /* ƒz?ƒŠ?ƒNƒƒX */ if( rand()%100 < 3*skilllv*sc_def_int/100 ) - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case CR_GRANDCROSS: /* ƒOƒ‰ƒ“ƒhƒNƒƒX */ + case NPC_DARKGRANDCROSS: /*ˆÅƒOƒ‰ƒ“ƒhƒNƒƒX*/ { - int race = battle_get_race(bl); - if( (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6) && rand()%100 < 100000*sc_def_int/100) //?§•t?‚¾‚ªŠ®‘S‘Ï«‚ɂ͖³? - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + int race = status_get_race(bl); + if( (battle_check_undead(race,status_get_elem_type(bl)) || race == 6) && rand()%100 < 100000*sc_def_int/100) //?§•t?‚¾‚ªŠ®‘S‘Ï«‚ɂ͖³? + status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); } break; + case AM_ACIDTERROR: + if( rand()%100 < (skilllv*3)*sc_def_vit/100 ) + status_change_start(bl,SC_BLEEDING,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + break; + case CR_SHIELDCHARGE: /* ƒV?ƒ‹ƒhƒ`ƒƒ?ƒW */ if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case RG_RAID: /* ƒTƒvƒ‰ƒCƒYƒAƒ^ƒbƒN */ if( rand()%100 < (10+3*skilllv)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); if( rand()%100 < (10+3*skilllv)*sc_def_int/100 ) - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case BA_FROSTJOKE: if(rand()%100 < (15+5*skilllv)*sc_def_mdef/100) - skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case DC_SCREAM: if( rand()%100 < (25+5*skilllv)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case BD_LULLABY: /* ŽqŽç‰S */ if( rand()%100 < 15*sc_def_int/100 ) - skill_status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; /* MOB‚̒ljÁ?‰Ê•t‚«ƒXƒLƒ‹ */ case NPC_PETRIFYATTACK: if(rand()%100 < sc_def_mdef) - skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case NPC_POISON: case NPC_SILENCEATTACK: case NPC_STUNATTACK: if(rand()%100 < sc_def_vit && src->type!=BL_PET) - skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); if(src->type==BL_PET) - skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skilllv*1000,0); + status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skilllv*1000,0); break; case NPC_CURSEATTACK: if(rand()%100 < sc_def_luk) - skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case NPC_SLEEPATTACK: case NPC_BLINDATTACK: if(rand()%100 < sc_def_int) - skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case NPC_MENTALBREAKER: if(dstsd) { @@ -1247,126 +952,164 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s // case WZ_METEOR: if(rand()%100 < sc_def_vit) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case WZ_VERMILION: if(rand()%100 < sc_def_int) - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; // -- moonsoul (stun ability of new champion skill tigerfist) // case CH_TIGERFIST: - if( rand()%100 < (10 + skilllv*10)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + if (rand()%100 < (10 + skilllv*10)*sc_def_vit/100) { + int sec = skill_get_time2 (skillid,skilllv) - status_get_agi(bl)/10; + if (dstsd) { + dstsd->canmove_tick += sec; + dstsd->canact_tick += sec; + } else if (dstmd) + dstmd->canmove_tick += sec; + } break; case LK_SPIRALPIERCE: if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case ST_REJECTSWORD: /* ƒtƒŠ?ƒWƒ“ƒOƒgƒ‰ƒbƒv */ if( rand()%100 < (skilllv*15) ) - skill_status_change_start(bl,SC_AUTOCOUNTER,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_AUTOCOUNTER,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case PF_FOGWALL: /* ƒz?ƒŠ?ƒNƒƒX */ - if( rand()%100 < 3*skilllv*sc_def_int/100 ) - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + if (src != bl) { + struct status_change *sc_data = status_get_sc_data(bl); + if (sc_data && sc_data[SC_DELUGE].timer == -1) + status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + } break; case LK_HEADCRUSH: /* ƒwƒbƒhƒNƒ‰ƒbƒVƒ… */ {//?Œ‚ª—Ç‚•ª‚©‚ç‚È‚¢‚̂œK?‚É - int race=battle_get_race(bl); - if( !(battle_check_undead(race,battle_get_elem_type(bl)) || race == 6) && rand()%100 < (2*skilllv+10)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_HEADCRUSH,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + int race=status_get_race(bl); + if( !(battle_check_undead(race,status_get_elem_type(bl)) || race == 6) && rand()%100 < (2*skilllv+10)*sc_def_vit/100 ) + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); } break; case LK_JOINTBEAT: /* ƒWƒ‡ƒCƒ“ƒgƒr?ƒg */ //?Œ‚ª—Ç‚•ª‚©‚ç‚È‚¢‚̂œK?‚É - if( rand()%100 < (2*skilllv+10)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_JOINTBEAT,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + if( rand()%100 < (5*skilllv+5)*sc_def_vit/100 ) + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case PF_SPIDERWEB: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ { - if(bl->type == BL_MOB) - { - int sec=skill_get_time2(skillid,skilllv); - if(map[src->m].flag.pvp) //PvP‚Å‚ÍS‘©ŽžŠÔ”¼Œ¸H - sec = sec/2; - battle_stopwalking(bl,1); - skill_status_change_start(bl,SC_SPIDERWEB,skilllv,0,0,0,sec,0); - } + int sec = skill_get_time2(skillid,skilllv); + if(map[src->m].flag.pvp) //PvP‚Å‚ÍS‘©ŽžŠÔ”¼Œ¸H + sec = sec/2; + battle_stopwalking(bl,1); + status_change_start(bl,SC_SPIDERWEB,skilllv,0,0,0,sec,0); } break; case ASC_METEORASSAULT: /* ƒƒeƒIƒAƒTƒ‹ƒg */ if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 ) //?‘ÔˆÙí‚ÍÚׂª•ª‚©‚ç‚È‚¢‚̂œK?‚É - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); if( rand()%100 < (10+3*skilllv)*sc_def_int/100 ) - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case MO_EXTREMITYFIST: /* ˆ¢C—…”e™€Œ */ //ˆ¢C—…‚ðŽg‚¤‚Æ5•ªŠÔŽ©‘R‰ñ•œ‚µ‚È‚¢‚悤‚ɂȂé - skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0 ); + status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0 ); break; case HW_NAPALMVULCAN: /* ƒiƒp?ƒ€ƒoƒ‹ƒJƒ“ */ // skilllv*5%‚ÌŠm—¦‚ÅŽô‚¢ if (rand()%10000 < 5*skilllv*sc_def_luk) - skill_status_change_start(bl,SC_CURSE,7,0,0,0,skill_get_time2(NPC_CURSEATTACK,7),0); + status_change_start(bl,SC_CURSE,7,0,0,0,skill_get_time2(NPC_CURSEATTACK,7),0); break; } - if(sd && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){ /* ƒJ?ƒh‚É‚æ‚é’ljÁ?‰Ê */ - int i; + if((sd||dstsd) && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){ /* ƒJ?ƒh‚É‚æ‚é’ljÁ?‰Ê */ + int i, type; int sc_def_card=100; for(i=SC_STONE;i<=SC_BLIND;i++){ + type=i-SC_STONE; //?Û‚É?‘ÔˆÙí - if(i==SC_STONE || i==SC_FREEZE) - sc_def_card=sc_def_mdef; - else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE) - sc_def_card=sc_def_vit; - else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND) - sc_def_card=sc_def_int; - else if(i==SC_CURSE) - sc_def_card=sc_def_luk; - - if(!sd->state.arrow_atk) { - if(rand()%10000 < (sd->addeff[i-SC_STONE])*sc_def_card/100 ){ - if(battle_config.battle_log) - printf("PC %d skill_addeff: card‚É‚æ‚éˆÙí?“® %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]); - skill_status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); - } + switch (i) { + case SC_STONE: + case SC_FREEZE: + sc_def_card=sc_def_mdef; + break; + case SC_STAN: + case SC_POISON: + case SC_SILENCE: + sc_def_card=sc_def_vit; + break; + case SC_SLEEP: + case SC_CONFUSION: + case SC_BLIND: + sc_def_card=sc_def_int; + break; + case SC_CURSE: + sc_def_card=sc_def_luk; } - else { - if(rand()%10000 < (sd->addeff[i-SC_STONE]+sd->arrow_addeff[i-SC_STONE])*sc_def_card/100 ){ - if(battle_config.battle_log) - printf("PC %d skill_addeff: card‚É‚æ‚éˆÙí?“® %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]); - skill_status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); + + if (sd) { + if(!sd->state.arrow_atk) { + if(rand()%10000 < (sd->addeff[type])*sc_def_card/100 ){ + if(battle_config.battle_log) + printf("PC %d skill_addeff: card‚É‚æ‚éˆÙí?“® %d %d\n",sd->bl.id,i,sd->addeff[type]); + status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0); + } + } + else { + if(rand()%10000 < (sd->addeff[type]+sd->arrow_addeff[type])*sc_def_card/100 ){ + if(battle_config.battle_log) + printf("PC %d skill_addeff: card‚É‚æ‚éˆÙí?“® %d %d\n",sd->bl.id,i,sd->addeff[type]); + status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0); + } } } //Ž©•ª‚É?‘ÔˆÙí - if(i==SC_STONE || i==SC_FREEZE) - sc_def_card=sc_def_mdef2; - else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE) - sc_def_card=sc_def_vit2; - else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND) - sc_def_card=sc_def_int2; - else if(i==SC_CURSE) - sc_def_card=sc_def_luk2; - - if(!sd->state.arrow_atk) { - if(rand()%10000 < (sd->addeff2[i-SC_STONE])*sc_def_card/100 ){ - if(battle_config.battle_log) - printf("PC %d skill_addeff: card‚É‚æ‚éˆÙí?“® %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]); - skill_status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); - } + switch (i) { + case SC_STONE: + case SC_FREEZE: + sc_def_card=sc_def_mdef2; + break; + case SC_STAN: + case SC_POISON: + case SC_SILENCE: + sc_def_card=sc_def_vit2; + break; + case SC_SLEEP: + case SC_CONFUSION: + case SC_BLIND: + sc_def_card=sc_def_int2; + break; + case SC_CURSE: + sc_def_card=sc_def_luk2; } - else { - if(rand()%10000 < (sd->addeff2[i-SC_STONE]+sd->arrow_addeff2[i-SC_STONE])*sc_def_card/100 ){ - if(battle_config.battle_log) - printf("PC %d skill_addeff: card‚É‚æ‚éˆÙí?“® %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]); - skill_status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); + + if (sd) { + if(!sd->state.arrow_atk) { + if(rand()%10000 < (sd->addeff2[type])*sc_def_card/100 ){ + if(battle_config.battle_log) + printf("PC %d skill_addeff: card‚É‚æ‚éˆÙí?“® %d %d\n",src->id,i,sd->addeff2[type]); + status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0); + } + } + else { + if(rand()%10000 < (sd->addeff2[type]+sd->arrow_addeff2[type])*sc_def_card/100 ){ + if(battle_config.battle_log) + printf("PC %d skill_addeff: card‚É‚æ‚éˆÙí?“® %d %d\n",src->id,i,sd->addeff2[type]); + status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0); + } } } + if (dstsd && rand()%10000 < dstsd->addeff3[type]*sc_def_card/100){ + if (dstsd->addeff3_type[type] != 1 && ((sd && !sd->state.arrow_atk) || (status_get_range(src)<=2))) + continue; + if(battle_config.battle_log) + printf("PC %d skill_addeff: card‚É‚æ‚éˆÙí?“® %d %d\n",src->id,i,dstsd->addeff3[type]); + status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0); + } } } return 0; @@ -1379,7 +1122,7 @@ int skill_blown( struct block_list *src, struct block_list *target,int count) { int dx=0,dy=0,nx,ny; int x=target->x,y=target->y; - int ret,prev_state=MS_IDLE; + int dir,ret,prev_state=MS_IDLE; int moveblock; struct map_session_data *sd=NULL; struct mob_data *md=NULL; @@ -1390,25 +1133,24 @@ int skill_blown( struct block_list *src, struct block_list *target,int count) nullpo_retr(0, target); if(target->type==BL_PC){ - nullpo_retr(0, sd=(struct map_session_data *)target); + sd=(struct map_session_data *)target; }else if(target->type==BL_MOB){ - nullpo_retr(0, md=(struct mob_data *)target); + md=(struct mob_data *)target; }else if(target->type==BL_PET){ - nullpo_retr(0, pd=(struct pet_data *)target); + pd=(struct pet_data *)target; }else if(target->type==BL_SKILL){ - nullpo_retr(0, su=(struct skill_unit *)target); + su=(struct skill_unit *)target; }else return 0; - if(!(count&0x10000 && (sd||md||pd||su))){ /* Žw’è‚È‚µ‚È‚çˆÊ’u?ŒW‚©‚ç•ûŒü‚ð‹‚ß‚é */ - dx=target->x-src->x; dx=(dx>0)?1:((dx<0)?-1: 0); - dy=target->y-src->y; dy=(dy>0)?1:((dy<0)?-1: 0); - } - if(dx==0 && dy==0){ - int dir=battle_get_dir(target); - if(dir>=0 && dir<8){ - dx=-dirx[dir]; - dy=-diry[dir]; - } + if (count&0xf00000) + dir = (count>>20)&0xf; + else if (count&0x10000 || (target->x==src->x && target->y==src->y)) + dir = status_get_dir(target); + else + dir = map_calc_dir(target,src->x,src->y); + if (dir>=0 && dir<8){ + dx = -dirx[dir]; + dy = -diry[dir]; } ret=path_blownpos(target->m,x,y,dx,dy,count&0xffff); @@ -1456,18 +1198,13 @@ int skill_blown( struct block_list *src, struct block_list *target,int count) if(su){ skill_unit_move_unit_group(su->group,target->m,dx,dy); }else{ -// struct status_change *sc_data=battle_get_sc_data(target); - if(moveblock) map_delblock(target); - target->x=nx; - target->y=ny; - if(moveblock) map_addblock(target); -/*ƒ_ƒ“ƒX’†‚ɃGƒtƒFƒNƒg‚͈ړ®‚µ‚È‚¢‚炵‚¢ - if(sc_data && sc_data[SC_DANCING].timer!=-1){ //?Û‚ªƒ_ƒ“ƒX’†‚Ȃ̂ŃGƒtƒFƒNƒg‚àˆÚ“® - struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[SC_DANCING].val2; - if(sg) - skill_unit_move_unit_group(sg,target->m,dx,dy); - } -*/ + int tick = gettick(); + skill_unit_move(target,tick,0); + if(moveblock) map_delblock(target); + target->x=nx; + target->y=ny; + if(moveblock) map_addblock(target); + skill_unit_move(target,tick,1); } if(sd) { /* ?–Ê?‚É“ü‚Á‚Ä‚«‚½‚̂ŕ\ަ */ @@ -1486,8 +1223,6 @@ int skill_blown( struct block_list *src, struct block_list *target,int count) pd->state.state = prev_state; } - skill_unit_move(target,gettick(),(count&0xffff)+7); /* ƒXƒLƒ‹ƒ†ƒjƒbƒg‚Ì”»’è */ - return 0; } @@ -1510,15 +1245,16 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds struct Damage dmg; struct status_change *sc_data; int type,lv,damage; + static int tmpdmg = 0; - if(skilllv <= 0) return 0; + if(skillid > 0 && skilllv <= 0) return 0; rdamage = 0; nullpo_retr(0, src); nullpo_retr(0, dsrc); nullpo_retr(0, bl); - sc_data = battle_get_sc_data(bl); + sc_data = status_get_sc_data(bl); //‰½‚à‚µ‚È‚¢”»’肱‚±‚©‚ç if(dsrc->m != bl->m) //?Û‚ª“¯‚¶ƒ}ƒbƒv‚É‚¢‚È‚¯‚ê‚Ή½‚à‚µ‚È‚¢ @@ -1527,11 +1263,11 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds return 0; if(src->type == BL_PC && pc_isdead((struct map_session_data *)src)) //pŽÒH‚ªPC‚Å‚·‚łɎ€‚ñ‚Å‚¢‚½‚牽‚à‚µ‚È‚¢ return 0; - if(dsrc->type == BL_PC && pc_isdead((struct map_session_data *)dsrc)) //pŽÒH‚ªPC‚Å‚·‚łɎ€‚ñ‚Å‚¢‚½‚牽‚à‚µ‚È‚¢ + if(src != dsrc && dsrc->type == BL_PC && pc_isdead((struct map_session_data *)dsrc)) //pŽÒH‚ªPC‚Å‚·‚łɎ€‚ñ‚Å‚¢‚½‚牽‚à‚µ‚È‚¢ return 0; if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) //?Û‚ªPC‚Å‚·‚łɎ€‚ñ‚Å‚¢‚½‚牽‚à‚µ‚È‚¢ return 0; - if(bl->type == BL_PC && skillnotok(skillid, (struct map_session_data *) bl)) + if(bl->type == BL_PC && skillnotok(skillid, (struct map_session_data *)bl)) return 0; // [MouseJstr] if(sc_data && sc_data[SC_HIDING].timer != -1) { //ƒnƒCƒfƒBƒ“ƒO?‘Ô‚Å if(skill_get_pl(skillid) != 2) //ƒXƒLƒ‹‚Ì?«‚ª’n?«‚łȂ¯‚ê‚Ή½‚à‚µ‚È‚¢ @@ -1562,27 +1298,30 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds if(attack_type&BF_MAGIC && sc_data && sc_data[SC_MAGICROD].timer != -1 && src == dsrc) { //–‚–@U?‚Ń}ƒWƒbƒNƒƒbƒh?‘Ô‚Åsrc=dsrc‚È‚ç dmg.damage = dmg.damage2 = 0; //ƒ_ƒ?ƒW0 if(bl->type == BL_PC) { //?Û‚ªPC‚Ìê‡ - int sp = skill_get_sp(skillid,skilllv); //Žg—p‚³‚ꂽƒXƒLƒ‹‚ÌSP‚ð‹z? - sp = sp * sc_data[SC_MAGICROD].val2 / 100; //‹z?—¦ŒvŽZ - if(skillid == WZ_WATERBALL && skilllv > 1) //ƒEƒH?ƒ^?ƒ{?ƒ‹Lv1ˆÈã - sp = sp/((skilllv|1)*(skilllv|1)); //‚³‚ç‚ÉŒvŽZH - if(sp > 0x7fff) sp = 0x7fff; //SP‘½‚·‚¬‚Ìꇂ͗˜_Å‘å’l - else if(sp < 1) sp = 1; //1ˆÈ‰º‚ÌꇂÍ1 - if(((struct map_session_data *)bl)->status.sp + sp > ((struct map_session_data *)bl)->status.max_sp) { //‰ñ•œSP+Œ»Ý‚ÌSP‚ªMSP‚æ‚è‘å‚«‚¢ê‡ - sp = ((struct map_session_data *)bl)->status.max_sp - ((struct map_session_data *)bl)->status.sp; //SP‚ðMSP-Œ»ÝSP‚É‚·‚é - ((struct map_session_data *)bl)->status.sp = ((struct map_session_data *)bl)->status.max_sp; //Œ»Ý‚ÌSP‚ÉMSP‚ð‘ã“ü - } - else //‰ñ•œSP+Œ»Ý‚ÌSP‚ªMSP‚æ‚謂³‚¢ê‡‚͉ñ•œSP‚ð‰ÁŽZ - ((struct map_session_data *)bl)->status.sp += sp; - clif_heal(((struct map_session_data *)bl)->fd,SP_SP,sp); //SP‰ñ•œƒGƒtƒFƒNƒg‚Ì•\ަ - ((struct map_session_data *)bl)->canact_tick = tick + skill_delayfix(bl, skill_get_delay(SA_MAGICROD,sc_data[SC_MAGICROD].val1)); // + struct map_session_data *sd = (struct map_session_data *)bl; + if (sd) { + int sp = skill_get_sp(skillid,skilllv); //Žg—p‚³‚ꂽƒXƒLƒ‹‚ÌSP‚ð‹z? + sp = sp * sc_data[SC_MAGICROD].val2 / 100; //‹z?—¦ŒvŽZ + if(skillid == WZ_WATERBALL && skilllv > 1) //ƒEƒH?ƒ^?ƒ{?ƒ‹Lv1ˆÈã + sp = sp/((skilllv|1)*(skilllv|1)); //‚³‚ç‚ÉŒvŽZH + if(sp > 0x7fff) sp = 0x7fff; //SP‘½‚·‚¬‚Ìꇂ͗˜_Å‘å’l + else if(sp < 1) sp = 1; //1ˆÈ‰º‚ÌꇂÍ1 + if(sd->status.sp + sp > sd->status.max_sp) { //‰ñ•œSP+Œ»Ý‚ÌSP‚ªMSP‚æ‚è‘å‚«‚¢ê‡ + sp = sd->status.max_sp - sd->status.sp; //SP‚ðMSP-Œ»ÝSP‚É‚·‚é + sd->status.sp = sd->status.max_sp; //Œ»Ý‚ÌSP‚ÉMSP‚ð‘ã“ü + } + else //‰ñ•œSP+Œ»Ý‚ÌSP‚ªMSP‚æ‚謂³‚¢ê‡‚͉ñ•œSP‚ð‰ÁŽZ + sd->status.sp += sp; + clif_heal(sd->fd,SP_SP,sp); //SP‰ñ•œƒGƒtƒFƒNƒg‚Ì•\ަ + sd->canact_tick = tick + skill_delayfix(bl, skill_get_delay(SA_MAGICROD,sc_data[SC_MAGICROD].val1)); // + } } clif_skill_nodamage(bl,bl,SA_MAGICROD,sc_data[SC_MAGICROD].val1,1); //ƒ}ƒWƒbƒNƒƒbƒhƒGƒtƒFƒNƒg‚ð•\ަ } //ƒ}ƒWƒbƒNƒƒbƒh?—‚±‚±‚܂Šif(src->type==BL_PET) { // [Valaris] - dmg.damage=battle_attr_fix(skilllv, skill_get_pl(skillid), battle_get_element(bl) ); + dmg.damage=battle_attr_fix(skilllv, skill_get_pl(skillid), status_get_element(bl) ); dmg.damage2=0; } @@ -1597,7 +1336,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds if(damage <= 0 || damage < dmg.div_) //‚«”ò‚΂µ”»’èH¦ dmg.blewcount = 0; - if(skillid == CR_GRANDCROSS) {//ƒOƒ‰ƒ“ƒhƒNƒƒX + if(skillid == CR_GRANDCROSS||skillid == NPC_DARKGRANDCROSS) {//ƒOƒ‰ƒ“ƒhƒNƒƒX if(battle_config.gx_disptype) dsrc = src; // “Gƒ_ƒ?ƒW”’•¶Žš•\ަ if( src == bl) type = 4; // ”½“®‚̓_ƒ?ƒWƒ‚?ƒVƒ‡ƒ“‚È‚µ } @@ -1608,12 +1347,12 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds nullpo_retr(0, sd); //˜A‘Ŷ(MO_CHAINCOMBO)‚±‚±‚©‚ç if(skillid == MO_CHAINCOMBO) { - int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src); //Šî–{ƒfƒBƒŒƒC‚ÌŒvŽZ - if(damage < battle_get_hp(bl)) { //ƒ_ƒ?ƒW‚ª?Û‚ÌHP‚æ‚謂³‚¢ê‡ + int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src); //Šî–{ƒfƒBƒŒƒC‚ÌŒvŽZ + if(damage < status_get_hp(bl)) { //ƒ_ƒ?ƒW‚ª?Û‚ÌHP‚æ‚謂³‚¢ê‡ if(pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0) //–Ò—´Œ(MO_COMBOFINISH)Žæ“¾•?‹…•ÛŽŽž‚Í+300ms delay += 300 * battle_config.combo_delay_rate /100; //’ljÁƒfƒBƒŒƒC‚ðconf‚É‚æ‚è’²® - skill_status_change_start(src,SC_COMBO,MO_CHAINCOMBO,skilllv,0,0,delay,0); //ƒRƒ“ƒ{?‘Ô‚É + status_change_start(src,SC_COMBO,MO_CHAINCOMBO,skilllv,0,0,delay,0); //ƒRƒ“ƒ{?‘Ô‚É } sd->attackabletime = sd->canmove_tick = tick + delay; clif_combo_delay(src,delay); //ƒRƒ“ƒ{ƒfƒBƒŒƒCƒpƒPƒbƒg‚Ì‘—M @@ -1621,8 +1360,8 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds //˜A‘Ŷ(MO_CHAINCOMBO)‚±‚±‚܂Š//–Ò—´Œ(MO_COMBOFINISH)‚±‚±‚©‚ç else if(skillid == MO_COMBOFINISH) { - int delay = 700 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src); - if(damage < battle_get_hp(bl)) { + int delay = 700 - 4 * status_get_agi(src) - 2 * status_get_dex(src); + if(damage < status_get_hp(bl)) { //ˆ¢C—…”e™€Œ(MO_EXTREMITYFIST)Žæ“¾•?‹…4ŒÂ•ÛŽ•”š—ô”g“®(MO_EXPLOSIONSPIRITS)?‘ÔŽž‚Í+300ms //•šŒÕŒ(CH_TIGERFIST)Žæ“¾Žž‚à+300ms if((pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball >= 4 && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1) || @@ -1630,7 +1369,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds (pc_checkskill(sd, CH_CHAINCRUSH) > 0 && sd->spiritball > 1)) delay += 300 * battle_config.combo_delay_rate /100; //’ljÁƒfƒBƒŒƒC‚ðconf‚É‚æ‚è’²® - skill_status_change_start(src,SC_COMBO,MO_COMBOFINISH,skilllv,0,0,delay,0); //ƒRƒ“ƒ{?‘Ô‚É + status_change_start(src,SC_COMBO,MO_COMBOFINISH,skilllv,0,0,delay,0); //ƒRƒ“ƒ{?‘Ô‚É } sd->attackabletime = sd->canmove_tick = tick + delay; clif_combo_delay(src,delay); //ƒRƒ“ƒ{ƒfƒBƒŒƒCƒpƒPƒbƒg‚Ì‘—M @@ -1638,12 +1377,12 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds //–Ò—´Œ(MO_COMBOFINISH)‚±‚±‚܂Š//•šŒÕŒ(CH_TIGERFIST)‚±‚±‚©‚ç else if(skillid == CH_TIGERFIST) { - int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src); - if(damage < battle_get_hp(bl)) { + int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src); + if(damage < status_get_hp(bl)) { if(pc_checkskill(sd, CH_CHAINCRUSH) > 0) //˜A’Œ•ö?(CH_CHAINCRUSH)Žæ“¾Žž‚Í+300ms delay += 300 * battle_config.combo_delay_rate /100; //’ljÁƒfƒBƒŒƒC‚ðconf‚É‚æ‚è’²® - skill_status_change_start(src,SC_COMBO,CH_TIGERFIST,skilllv,0,0,delay,0); //ƒRƒ“ƒ{?‘Ô‚É + status_change_start(src,SC_COMBO,CH_TIGERFIST,skilllv,0,0,delay,0); //ƒRƒ“ƒ{?‘Ô‚É } sd->attackabletime = sd->canmove_tick = tick + delay; clif_combo_delay(src,delay); //ƒRƒ“ƒ{ƒfƒBƒŒƒCƒpƒPƒbƒg‚Ì‘—M @@ -1651,13 +1390,13 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds //•šŒÕŒ(CH_TIGERFIST)‚±‚±‚܂Š//˜A’Œ•ö?(CH_CHAINCRUSH)‚±‚±‚©‚ç else if(skillid == CH_CHAINCRUSH) { - int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src); - if(damage < battle_get_hp(bl)) { + int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src); + if(damage < status_get_hp(bl)) { //ˆ¢C—…”e™€Œ(MO_EXTREMITYFIST)Žæ“¾•?‹…4ŒÂ•ÛŽ•”š—ô”g“®(MO_EXPLOSIONSPIRITS)?‘ÔŽž‚Í+300ms if(pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball >= 4 && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1) delay += 300 * battle_config.combo_delay_rate /100; //’ljÁƒfƒBƒŒƒC‚ðconf‚É‚æ‚è’²® - skill_status_change_start(src,SC_COMBO,CH_CHAINCRUSH,skilllv,0,0,delay,0); //ƒRƒ“ƒ{?‘Ô‚É + status_change_start(src,SC_COMBO,CH_CHAINCRUSH,skilllv,0,0,delay,0); //ƒRƒ“ƒ{?‘Ô‚É } sd->attackabletime = sd->canmove_tick = tick + delay; clif_combo_delay(src,delay); //ƒRƒ“ƒ{ƒfƒBƒŒƒCƒpƒPƒbƒg‚Ì‘—M @@ -1708,23 +1447,32 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds //•ŠíƒXƒLƒ‹H‚±‚±‚܂Šswitch(skillid){ - case WZ_SIGHTRASHER: - clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, 5); - break; case AS_SPLASHER: clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, -1, 5); break; + case ASC_BREAKER: // [celest] + if (attack_type&BF_MAGIC) { // only display damage for the 2nd attack + if (damage + tmpdmg != 0) // if both attacks missed, do not display a 2nd 'miss' + clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, damage+tmpdmg, dmg.div_, skillid, skilllv, type); + tmpdmg = 0; // clear the temporary damage + } else { + if (damage == 0) // if weapon attack missed, display the 'miss' + clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, 0, dmg.div_, skillid, skilllv, type); + tmpdmg = damage; // store the temporary weapon damage + } + break; case NPC_SELFDESTRUCTION: case NPC_SELFDESTRUCTION2: break; + case SN_SHARPSHOOTING: + clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,0,0,0); + break; default: clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, (skillid==0)? 5:type ); } - if(dmg.blewcount > 0 && !map[src->m].flag.gvg) { /* ‚«”ò‚΂µ?—‚Æ‚»‚̃pƒPƒbƒg */ - if(skillid == WZ_SIGHTRASHER) - skill_blown(src,bl,dmg.blewcount); - else - skill_blown(dsrc,bl,dmg.blewcount); + /* ‚«”ò‚΂µˆ—‚Æ‚»‚̃pƒPƒbƒg */ + if (dmg.blewcount > 0 && bl->type!=BL_SKILL && !map[src->m].flag.gvg) { + skill_blown(dsrc,bl,dmg.blewcount); if(bl->type == BL_MOB) clif_fixmobpos((struct mob_data *)bl); else if(bl->type == BL_PET) @@ -1735,28 +1483,31 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds map_freeblock_lock(); /* ?ۂɃ_ƒ?ƒW?—‚ðs‚¤ */ - if(skillid != KN_BOWLINGBASH || flag) - battle_damage(src,bl,damage,0); - if(skillid == RG_INTIMIDATE && damage > 0 && !(battle_get_mode(bl)&0x20) && !map[src->m].flag.gvg ) { - int s_lv = battle_get_lv(src),t_lv = battle_get_lv(bl); + if (skillid || flag) { + if (attack_type&BF_WEAPON) + battle_delay_damage(tick+dmg.amotion,src,bl,damage,0); + else + battle_damage(src,bl,damage,0); + } + if(skillid == RG_INTIMIDATE && damage > 0 && !(status_get_mode(bl)&0x20) && !map[src->m].flag.gvg ) { + int s_lv = status_get_lv(src),t_lv = status_get_lv(bl); int rate = 50 + skilllv * 5; rate = rate + (s_lv - t_lv); if(rand()%100 < rate) skill_addtimerskill(src,tick + 800,bl->id,0,0,skillid,skilllv,0,flag); } - if(damage > 0 && dmg.flag&BF_SKILL && bl->type==BL_PC && pc_checkskill((struct map_session_data *)bl,RG_PLAGIARISM) && sc_data[SC_PRESERVE].timer != -1){ + if(damage > 0 && dmg.flag&BF_SKILL && bl->type==BL_PC && pc_checkskill((struct map_session_data *)bl,RG_PLAGIARISM) && sc_data[SC_PRESERVE].timer == -1){ struct map_session_data *tsd = (struct map_session_data *)bl; nullpo_retr(0, tsd); - if(!tsd->status.skill[skillid].id && !tsd->status.skill[skillid].id - && !(skillid > NPC_PIERCINGATT && skillid < NPC_SUMMONMONSTER) ){ + if(!tsd->status.skill[skillid].id && !tsd->status.skill[skillid].lv + && !(skillid > NPC_PIERCINGATT && skillid < NPC_SUMMONMONSTER) + && !(skillid > NPC_SELFDESTRUCTION2 && skillid < NPC_UNDEADATTACK)){ //?‚É?‚ñ‚Å‚¢‚éƒXƒLƒ‹‚ª‚ ‚ê‚ΊY?ƒXƒLƒ‹‚ðÁ‚· - if (tsd->cloneskill_id && tsd->cloneskill_lv && tsd->status.skill[tsd->cloneskill_id].flag==13){ + if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag==13){ tsd->status.skill[tsd->cloneskill_id].id=0; - tsd->status.skill[tsd->cloneskill_id].lv=0; tsd->status.skill[tsd->cloneskill_id].flag=0; } tsd->cloneskill_id=skillid; - tsd->cloneskill_lv=skilllv; tsd->status.skill[skillid].id=skillid; tsd->status.skill[skillid].lv=(pc_checkskill(tsd,RG_PLAGIARISM) > skill_get_max(skillid))? skill_get_max(skillid):pc_checkskill(tsd,RG_PLAGIARISM); @@ -1766,13 +1517,11 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds } /* ƒ_ƒ?ƒW‚ª‚ ‚é‚È‚ç’ljÁ?‰Ê”»’è */ if(bl->prev != NULL){ - struct map_session_data *sd = (struct map_session_data *)bl; - nullpo_retr(0, sd); - if( bl->type != BL_PC || (sd && !pc_isdead(sd)) ) { - if(damage > 0) - skill_additional_effect(src,bl,skillid,skilllv,attack_type,tick); - if(bl->type==BL_MOB && src!=bl) /* ƒXƒLƒ‹Žg—p?Œ‚ÌMOBƒXƒLƒ‹ */ - { + if(!status_isdead(bl)) { + if(damage > 0) + skill_additional_effect(src,bl,skillid,skilllv,attack_type,tick); + if(bl->type==BL_MOB && src!=bl) /* ƒXƒLƒ‹Žg—p?Œ‚ÌMOBƒXƒLƒ‹ */ + { struct mob_data *md=(struct mob_data *)bl; nullpo_retr(0, md); if(battle_config.mob_changetarget_byskill == 1) @@ -1814,16 +1563,23 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds if(sd->sp_drain_rate_ > 0 && sp < 1) sp = 1; else if(sd->sp_drain_rate_ < 0 && sp > -1) sp = -1; } - if(hp || sp) pc_heal(sd,hp,sp); + if(hp || sp) + pc_heal(sd,hp,sp); + if (sd->sp_drain_type && bl->type == BL_PC) + battle_heal(NULL,bl,0,-sp,0); } - if((skillid != KN_BOWLINGBASH || flag) && rdamage > 0) - battle_damage(bl,src,rdamage,0); + if ((skillid || flag) && rdamage>0) { + if (attack_type&BF_WEAPON) + battle_delay_damage(tick+dmg.amotion,bl,src,rdamage,0); + else + battle_damage(bl,src,rdamage,0); + } if(attack_type&BF_WEAPON && sc_data && sc_data[SC_AUTOCOUNTER].timer != -1 && sc_data[SC_AUTOCOUNTER].val4 > 0) { if(sc_data[SC_AUTOCOUNTER].val3 == dsrc->id) battle_weapon_attack(bl,dsrc,tick,0x8000|sc_data[SC_AUTOCOUNTER].val1); - skill_status_change_end(bl,SC_AUTOCOUNTER,-1); + status_change_end(bl,SC_AUTOCOUNTER,-1); } map_freeblock_unlock(); @@ -1870,9 +1626,8 @@ int skill_area_sub( struct block_list *bl,va_list ap ) static int skill_check_unit_range_sub( struct block_list *bl,va_list ap ) { struct skill_unit *unit; - int *c,x,y,range,sx[4],sy[4]; - int t_range,tx[4],ty[4]; - int i,r_flag,skillid; + int *c; + int skillid,unit_id; nullpo_retr(0, bl); nullpo_retr(0, ap); @@ -1885,57 +1640,46 @@ static int skill_check_unit_range_sub( struct block_list *bl,va_list ap ) if(!unit->alive) return 0; - x = va_arg(ap,int); - y = va_arg(ap,int); - range = va_arg(ap,int); skillid = va_arg(ap,int); + unit_id = unit->group->unit_id; - if(skillid == MG_SAFETYWALL || skillid == AL_PNEUMA) { - if(unit->group->unit_id != 0x7e && unit->group->unit_id != 0x85) + if (skillid==MG_SAFETYWALL || skillid==AL_PNEUMA) { + if(unit_id != 0x7e && unit_id != 0x85) return 0; - } - else if(skillid == AL_WARP) { - if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92) + } else if (skillid==AL_WARP) { + if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92) return 0; - } - else if((skillid >= HT_SKIDTRAP && skillid <= HT_CLAYMORETRAP) || skillid == HT_TALKIEBOX) { - if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92) + } else if ((skillid>=HT_SKIDTRAP && skillid<=HT_CLAYMORETRAP) || skillid==HT_TALKIEBOX) { + if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92) return 0; - } - else if(skillid == WZ_FIREPILLAR) { - if(unit->group->unit_id != 0x87) + } else if (skillid==WZ_FIREPILLAR) { + if (unit_id!=0x87) return 0; - } - else return 0; - t_range=(unit->range!=0)? unit->range:unit->group->range; - tx[0] = tx[3] = unit->bl.x - t_range; - tx[1] = tx[2] = unit->bl.x + t_range; - ty[0] = ty[1] = unit->bl.y - t_range; - ty[2] = ty[3] = unit->bl.y + t_range; - sx[0] = sx[3] = x - range; - sx[1] = sx[2] = x + range; - sy[0] = sy[1] = y - range; - sy[2] = sy[3] = y + range; - for(i=r_flag=0;i<4;i++) { - if(sx[i] >= tx[0] && sx[i] <= tx[1] && sy[i] >= ty[0] && sy[i] <= ty[2]) { - r_flag = 1; - break; - } - if(tx[i] >= sx[0] && tx[i] <= sx[1] && ty[i] >= sy[0] && ty[i] <= sy[2]) { - r_flag = 1; - break; - } - } - if(r_flag) (*c)++; + } else if (skillid==HP_BASILICA) { + if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92 && unit_id!=0x83) + return 0; + } else + return 0; + + (*c)++; return 0; } -int skill_check_unit_range(int m,int x,int y,int range,int skillid) +int skill_check_unit_range(int m,int x,int y,int skillid,int skilllv) { int c = 0; + int range = skill_get_unit_range(skillid); + int layout_type = skill_get_unit_layout_type(skillid,skilllv); + if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) { + printf("skill_check_unit_range: unsupported layout type %d for skill %d\n",layout_type,skillid); + return 0; + } - map_foreachinarea(skill_check_unit_range_sub,m,x-10,y-10,x+10,y+10,BL_SKILL,&c,x,y,range,skillid); + // ‚Æ‚è‚ ‚¦‚¸³•ûŒ`‚̃†ƒjƒbƒgƒŒƒCƒAƒEƒg‚̂ݑΉž + range += layout_type; + map_foreachinarea(skill_check_unit_range_sub,m, + x-range,y-range,x+range,y+range,BL_SKILL,&c,skillid); return c; } @@ -1943,6 +1687,8 @@ int skill_check_unit_range(int m,int x,int y,int range,int skillid) static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap ) { int *c; + int skillid; + nullpo_retr(0, bl); nullpo_retr(0, ap); @@ -1954,32 +1700,117 @@ static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap ) if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) return 0; + skillid = va_arg(ap,int); + if (skillid==HP_BASILICA && bl->type==BL_PC) + return 0; + (*c)++; return 0; } -int skill_check_unit_range2(int m,int x,int y,int range) +int skill_check_unit_range2(struct block_list *bl, int m,int x,int y,int skillid, int skilllv) { - int c = 0; + int c = 0, range, type; + + switch (skillid) { // to be expanded later + case WZ_ICEWALL: + range = 2; + break; + default: + { + int layout_type = skill_get_unit_layout_type(skillid,skilllv); + if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) { + printf("skill_check_unit_range2: unsupported layout type %d for skill %d\n",layout_type,skillid); + return 0; + } + // ‚Æ‚è‚ ‚¦‚¸³•ûŒ`‚̃†ƒjƒbƒgƒŒƒCƒAƒEƒg‚̂ݑΉž + range = skill_get_unit_range(skillid) + layout_type; + } + break; + } - map_foreachinarea(skill_check_unit_range2_sub,m,x-range,y-range,x+range,y+range,0,&c); + // if the caster is a monster/NPC, only check for players + // otherwise just check everything + if (bl->type == BL_PC) + type = 0; + else type = BL_PC; + + map_foreachinarea(skill_check_unit_range2_sub, m, + x - range, y - range, x + range, y + range, + type, &c, skillid); return c; } +int skill_guildaura_sub (struct block_list *bl,va_list ap) +{ + struct map_session_data *sd; + struct guild *g; + int gid, id; + int flag = 0; + + nullpo_retr(0, sd=(struct map_session_data *)bl); + + nullpo_retr(0, ap); + id = va_arg(ap,int); + gid = va_arg(ap,int); + if (sd->status.guild_id != gid) + return 0; + + g = va_arg(ap,struct guild *); + if (guild_checkskill(g, GD_LEADERSHIP)>0) flag |= 1<<0; + if (guild_checkskill(g, GD_GLORYWOUNDS)>0) flag |= 1<<1; + if (guild_checkskill(g, GD_SOULCOLD)>0) flag |= 1<<2; + if (guild_checkskill(g, GD_HAWKEYES)>0) flag |= 1<<3; + if (guild_checkskill(g, GD_CHARISMA)>0) flag |= 1<<4; + + if (flag > 0) { + if (sd->sc_count && sd->sc_data[SC_GUILDAURA].timer != -1) { + if (sd->sc_data[SC_GUILDAURA].val4 != flag) { + sd->sc_data[SC_GUILDAURA].val4 = flag; + status_calc_pc (sd, 0); + } + return 0; + } + status_change_start(&sd->bl, SC_GUILDAURA,1,id,0,flag,0,0 ); + } + + return 0; +} + /*========================================================================= * ”Í?ƒXƒLƒ‹Žg—p?—¬•ª‚¯‚±‚±‚©‚ç */ /* ?Û‚Ì?‚ðƒJƒEƒ“ƒg‚·‚éBiskill_area_temp[0]‚ð‰Šú‰»‚µ‚Ä‚¨‚‚±‚Æj */ int skill_area_sub_count(struct block_list *src,struct block_list *target,int skillid,int skilllv,unsigned int tick,int flag) { - if(skilllv <= 0) return 0; if(skill_area_temp[0] < 0xffff) skill_area_temp[0]++; return 0; } +int skill_count_water(struct block_list *src,int range) +{ + int i,x,y,cnt = 0,size = range*2+1; + struct skill_unit *unit; + + for (i=0;i<size*size;i++) { + x = src->x+(i%size-range); + y = src->y+(i/size-range); + if (map_getcell(src->m,x,y,CELL_CHKWATER)) { + cnt++; + continue; + } + unit = map_find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL); + if (unit) { + cnt++; + skill_delunit(unit); + } + } + return cnt; +} + /*========================================== * *------------------------------------------ @@ -2017,6 +1848,10 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data ) nullpo_retr(0, skl); skl->timer = -1; + if (sd) { + sd->timerskill_count--; + } + if(skl->target_id) { struct block_list tbl; target = map_id2bl(skl->target_id); @@ -2045,13 +1880,13 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data ) break; case RG_INTIMIDATE: if(sd && !map[src->m].flag.noteleport) { - int x,y,i,j,c; + int x,y,i,j; pc_randomwarp(sd,3); for(i=0;i<16;i++) { j = rand()%8; x = sd->bl.x + dirx[j]; y = sd->bl.y + diry[j]; - if((c=map_getcell(sd->bl.m,x,y)) != 1 && c != 5) + if(map_getcell(sd->bl.m,x,y,CELL_CHKPASS)) break; } if(i >= 16) { @@ -2066,13 +1901,13 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data ) } } else if(md && !map[src->m].flag.monster_noteleport) { - int x,y,i,j,c; + int x,y,i,j; mob_warp(md,-1,-1,-1,3); for(i=0;i<16;i++) { j = rand()%8; x = md->bl.x + dirx[j]; y = md->bl.y + diry[j]; - if((c=map_getcell(md->bl.m,x,y)) != 1 && c != 5) + if(map_getcell(md->bl.m,x,y,CELL_CHKPASS)) break; } if(i >= 16) { @@ -2090,11 +1925,26 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data ) case BA_FROSTJOKE: /* Ц‚¢ƒWƒ‡?ƒN */ case DC_SCREAM: /* ƒXƒNƒŠ?ƒ€ */ - range=15; //Ž‹ŠE‘S? + range=battle_config.area_size; //Ž‹ŠE‘S? map_foreachinarea(skill_frostjoke_scream,src->m,src->x-range,src->y-range, src->x+range,src->y+range,0,src,skl->skill_id,skl->skill_lv,tick); break; + case WZ_WATERBALL: + if (skl->type>1) { + skl->timer = 0; // skill_addtimerskill‚ÅŽg—p‚³‚ê‚È‚¢‚悤‚É + skill_addtimerskill(src,tick+150,target->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag); + skl->timer = -1; + } + skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); + if (skl->type <= 1) { // partial fix: it still doesn't end if the target dies + // should put outside of the switch, but since this is the only + // mage targetted spell for now, + struct status_change *sc_data = status_get_sc_data(src); + if(sc_data && sc_data[SC_MAGICPOWER].timer != -1) //ƒ}ƒWƒbƒNƒpƒ?‚Ì?‰ÊI—¹ + status_change_end(src,SC_MAGICPOWER,-1); + } + break; default: skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); break; @@ -2143,6 +1993,7 @@ int skill_addtimerskill(struct block_list *src,unsigned int tick,int target,int sd->skilltimerskill[i].y = y; sd->skilltimerskill[i].type = type; sd->skilltimerskill[i].flag = flag; + sd->timerskill_count++; return 0; } @@ -2207,10 +2058,15 @@ int skill_cleartimerskill(struct block_list *src) if(src->type == BL_PC) { struct map_session_data *sd = (struct map_session_data *)src; nullpo_retr(0, sd); + + if (sd->timerskill_count <= 0) + return 0; + for(i=0;i<MAX_SKILLTIMERSKILL;i++) { if(sd->skilltimerskill[i].timer != -1) { delete_timer(sd->skilltimerskill[i].timer, skill_timerskill); sd->skilltimerskill[i].timer = -1; + sd->timerskill_count--; } } } @@ -2237,27 +2093,37 @@ int skill_cleartimerskill(struct block_list *src) * iƒXƒpƒQƒbƒeƒB‚ÉŒü‚¯‚Ä‚P?‘OiI(ƒ_ƒƒ|)j *------------------------------------------ */ -int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag ) +int skill_castend_damage_id (struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag) { - struct map_session_data *sd=NULL; - struct status_change *sc_data = battle_get_sc_data(src); + struct map_session_data *sd = NULL, *tsd = NULL; + struct status_change *sc_data; int i; - if(skilllv <= 0) return 0; + if(skillid < 0) + { // remove the debug print when this case is finished + printf("skill_castend_damage_id: skillid=%i\ncall: %p %p %i %i %i %i",skillid, + src, bl,skillid,skilllv,tick,flag); + return 0; + } + if(skillid > 0 && skilllv <= 0) return 0; nullpo_retr(1, src); nullpo_retr(1, bl); - if(src->type==BL_PC) - sd=(struct map_session_data *)src; - if(sd && pc_isdead(sd)) + sc_data = status_get_sc_data(src); + + if (src->type == BL_PC) + sd = (struct map_session_data *)src; + if (sd && pc_isdead(sd)) return 1; - if((skillid == WZ_SIGHTRASHER || skillid == CR_GRANDCROSS) && src != bl) + if ((skillid == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && src != bl) bl = src; - if(bl->prev == NULL) + if (bl->prev == NULL) return 1; - if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) + if (bl->type == BL_PC) + tsd = (struct map_session_data *)bl; + if (tsd && pc_isdead(tsd)) return 1; map_freeblock_lock(); @@ -2270,10 +2136,10 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s case AS_SONICBLOW: /* ƒ\ƒjƒbƒNƒuƒ? */ case KN_PIERCE: /* ƒsƒA?ƒX */ case KN_SPEARBOOMERANG: /* ƒXƒsƒAƒu?ƒƒ‰ƒ“ */ + case KN_BRANDISHSPEAR: /* ƒuƒ‰ƒ“ƒfƒBƒbƒVƒ…ƒXƒsƒA */ case TF_POISON: /* ƒCƒ“ƒxƒiƒ€ */ case TF_SPRINKLESAND: /* »‚Ü‚« */ case AC_CHARGEARROW: /* ƒ`ƒƒ?ƒWƒAƒ? */ - case KN_SPEARSTAB: /* ƒXƒsƒAƒXƒ^ƒu */ case RG_RAID: /* ƒTƒvƒ‰ƒCƒYƒAƒ^ƒbƒN */ case RG_INTIMIDATE: /* ƒCƒ“ƒeƒBƒ~ƒfƒCƒg */ case BA_MUSICALSTRIKE: /* ƒ~ƒ…?ƒWƒJƒ‹ƒXƒgƒ‰ƒCƒN */ @@ -2282,7 +2148,6 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s case CR_HOLYCROSS: /* ƒz?ƒŠ?ƒNƒƒX */ case CR_SHIELDCHARGE: case CR_SHIELDBOOMERANG: - /* ˆÈ‰ºMOB?—p */ /* ??U?ASPŒ¸U?A‰“‹——£U?A–hŒä–³Ž‹U?A‘½’iU? */ case NPC_PIERCINGATT: @@ -2311,187 +2176,195 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s case NPC_HOLYATTACK: case NPC_DARKNESSATTACK: case NPC_TELEKINESISATTACK: + case NPC_UNDEADATTACK: + case NPC_BREAKARMOR: + case NPC_BREAKWEAPON: + case NPC_BREAKHELM: + case NPC_BREAKSHIELD: case LK_AURABLADE: /* ƒI?ƒ‰ƒuƒŒ?ƒh */ case LK_SPIRALPIERCE: /* ƒXƒpƒCƒ‰ƒ‹ƒsƒA?ƒX */ case LK_HEADCRUSH: /* ƒwƒbƒhƒNƒ‰ƒbƒVƒ… */ case LK_JOINTBEAT: /* ƒWƒ‡ƒCƒ“ƒgƒr?ƒg */ - case PA_PRESSURE: /* ƒvƒŒƒbƒVƒƒ? */ - case PA_SACRIFICE: /* ƒTƒNƒŠƒtƒ@ƒCƒX */ - case SN_SHARPSHOOTING: /* ƒVƒƒ?ƒvƒVƒ…?ƒeƒBƒ“ƒO */ case CG_ARROWVULCAN: /* ƒAƒ?ƒoƒ‹ƒJƒ“ */ - case ASC_BREAKER: /* ƒ\ƒEƒ‹ƒuƒŒ?ƒJ? */ case HW_MAGICCRASHER: /* ƒ}ƒWƒbƒNƒNƒ‰ƒbƒVƒƒ? */ + case ASC_METEORASSAULT: /* ƒƒeƒIƒAƒTƒ‹ƒg */ + case ITM_TOMAHAWK: + case MO_COMBOFINISH: /* –Ò—´Œ */ + case CH_CHAINCRUSH: /* ˜A’Œ•ö? */ + case CH_PALMSTRIKE: /* –ÒŒÕd”hŽR */ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); break; + + case ASC_BREAKER: /* ƒ\ƒEƒ‹ƒuƒŒ?ƒJ? */ // [DracoRPG] + // separate weapon and magic attacks + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); + break; + + case SN_SHARPSHOOTING: /* ƒVƒƒ?ƒvƒVƒ…?ƒeƒBƒ“ƒO */ + map_foreachinpath (skill_attack_area,src->m, // function, map + src->x,src->y, // source xy + bl->x,bl->y, // target xy + 2,0, // range, type + BF_WEAPON,src,src,skillid,skilllv,tick,flag,BCT_ENEMY); // varargs + break; + + case PA_PRESSURE: /* ƒvƒŒƒbƒVƒƒ? */ + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + if (rand()%100 < 50) + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(PA_PRESSURE,skilllv),0); + else + status_change_start(bl,SC_BLEEDING,skilllv,0,0,0,skill_get_time2(PA_PRESSURE,skilllv),0); + if (tsd) { + int sp = tsd->status.max_sp * 10 * skilllv / 100; + if (sp > tsd->status.sp) sp = tsd->status.sp; + tsd->status.sp -= sp; + clif_updatestatus(tsd,SP_SP); + } + break; + case NPC_DARKBREATH: clif_emotion(src,7); skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); break; + case MO_INVESTIGATE: /* ?™¤ */ { - struct status_change *sc_data = battle_get_sc_data(src); skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if(sc_data[SC_BLADESTOP].timer != -1) - skill_status_change_end(src,SC_BLADESTOP,-1); + if (sc_data && sc_data[SC_BLADESTOP].timer != -1) + status_change_end(src,SC_BLADESTOP,-1); } break; + case SN_FALCONASSAULT: /* ƒtƒ@ƒ‹ƒRƒ“ƒAƒTƒ‹ƒg */ skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); break; - case KN_BRANDISHSPEAR: /* ƒuƒ‰ƒ“ƒfƒBƒbƒVƒ…ƒXƒsƒA */ - { - struct mob_data *md = (struct mob_data *)bl; - nullpo_retr(1, md); - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if(md->hp > 0){ - skill_blown(src,bl,skill_get_blewcount(skillid,skilllv)); - if(bl->type == BL_MOB) - clif_fixmobpos((struct mob_data *)bl); - else if(bl->type == BL_PET) - clif_fixpetpos((struct pet_data *)bl); - else - clif_fixpos(bl); - } - } - break; + case RG_BACKSTAP: /* ƒoƒbƒNƒXƒ^ƒu */ { - int dir = map_calc_dir(src,bl->x,bl->y),t_dir = battle_get_dir(bl); - int dist = distance(src->x,src->y,bl->x,bl->y); - if((dist > 0 && !map_check_dir(dir,t_dir)) || bl->type == BL_SKILL) { - struct status_change *sc_data = battle_get_sc_data(src); - if(sc_data && sc_data[SC_HIDING].timer != -1) - skill_status_change_end(src, SC_HIDING, -1); // ƒnƒCƒfƒBƒ“ƒO‰ðœ - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + int dir = map_calc_dir(src,bl->x,bl->y), t_dir = status_get_dir(bl); + int dist = distance(src->x, src->y, bl->x, bl->y); + if ((dist > 0 && !map_check_dir(dir, t_dir)) || bl->type == BL_SKILL) { + if (sc_data && sc_data[SC_HIDING].timer != -1) + status_change_end(src, SC_HIDING, -1); // ƒnƒCƒfƒBƒ“ƒO‰ðœ + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest] - if (bl->type == BL_PC) - ((struct map_session_data *)bl)->dir=dir; - else if (bl->type == BL_MOB) - ((struct mob_data *)bl)->dir=dir; - //skill_blown(src,bl,skill_get_blewcount(skillid,skilllv)); + if (tsd) + tsd->dir = dir; + else if (bl->type == BL_MOB) { + struct mob_data *md = (struct mob_data *)bl; + if (md) md->dir = dir; + } + clif_changed_dir(bl); } - else if(src->type == BL_PC) + else if (sd) clif_skill_fail(sd,sd->skillid,0,0); } break; case AM_ACIDTERROR: /* ƒAƒVƒbƒhƒeƒ‰? */ - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if(bl->type == BL_PC && rand()%100 < skill_get_time(skillid,skilllv) && battle_config.equipment_breaking) - pc_breakarmor((struct map_session_data *)bl); + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); + if (tsd && battle_config.equipment_breaking && rand()%100 < skill_get_time(skillid,skilllv)) { + pc_breakarmor(tsd); + clif_emotion(bl, 23); + } break; + case MO_FINGEROFFENSIVE: /* Žw? */ { - struct status_change *sc_data = battle_get_sc_data(src); - - if(!battle_config.finger_offensive_type) - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - else { - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if(sd) { - for(i=1;i<sd->spiritball_old;i++) - skill_addtimerskill(src,tick+i*200,bl->id,0,0,skillid,skilllv,BF_WEAPON,flag); - sd->canmove_tick = tick + (sd->spiritball_old-1)*200; - } + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + if (battle_config.finger_offensive_type && sd) { + for (i = 1; i < sd->spiritball_old; i++) + skill_addtimerskill(src, tick + i * 200, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag); + sd->canmove_tick = tick + (sd->spiritball_old - 1) * 200; } - if(sc_data && sc_data[SC_BLADESTOP].timer != -1) - skill_status_change_end(src,SC_BLADESTOP,-1); + if (sc_data && sc_data[SC_BLADESTOP].timer != -1) + status_change_end(src,SC_BLADESTOP,-1); } break; + case MO_CHAINCOMBO: /* ˜A‘Ŷ */ { - struct status_change *sc_data = battle_get_sc_data(src); skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if(sc_data && sc_data[SC_BLADESTOP].timer != -1) - skill_status_change_end(src,SC_BLADESTOP,-1); + if (sc_data && sc_data[SC_BLADESTOP].timer != -1) + status_change_end(src,SC_BLADESTOP,-1); } break; - case MO_COMBOFINISH: /* –Ò—´Œ */ + case CH_TIGERFIST: /* •šŒÕŒ */ - case CH_CHAINCRUSH: /* ˜A’Œ•ö? */ - case CH_PALMSTRIKE: /* –ÒŒÕd”hŽR */ + if (tsd && !(map[bl->m].flag.gvg || map[bl->m].flag.pvp)) { + map_freeblock_unlock(); + return 1; + } skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); break; + case MO_EXTREMITYFIST: /* ˆ¢C—…”e–PŒ */ { - struct status_change *sc_data = battle_get_sc_data(src); + if(sd) { + struct walkpath_data wpd; + int dx,dy; - if(sd) { - struct walkpath_data wpd; - int dx,dy; - - dx = bl->x - sd->bl.x; - dy = bl->y - sd->bl.y; - if(dx > 0) dx++; - else if(dx < 0) dx--; - if(dy > 0) dy++; - else if(dy < 0) dy--; - if(dx == 0 && dy == 0) dx++; - if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) { dx = bl->x - sd->bl.x; dy = bl->y - sd->bl.y; - if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) { - clif_skill_fail(sd,sd->skillid,0,0); - break; + if(dx > 0) dx++; + else if(dx < 0) dx--; + if (dy > 0) dy++; + else if(dy < 0) dy--; + if(dx == 0 && dy == 0) dx++; + if (path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) { + dx = bl->x - sd->bl.x; + dy = bl->y - sd->bl.y; + if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) { + clif_skill_fail(sd,sd->skillid,0,0); + break; + } } + sd->to_x = sd->bl.x + dx; + sd->to_y = sd->bl.y + dy; + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + clif_walkok(sd); + clif_movechar(sd); + if(dx < 0) dx = -dx; + if(dy < 0) dy = -dy; + sd->attackabletime = sd->canmove_tick = tick + 100 + sd->speed * ((dx > dy)? dx:dy); + if(sd->canact_tick < sd->canmove_tick) + sd->canact_tick = sd->canmove_tick; + pc_movepos(sd,sd->to_x,sd->to_y); + status_change_end(&sd->bl,SC_COMBO,-1); } - sd->to_x = sd->bl.x + dx; - sd->to_y = sd->bl.y + dy; - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - clif_walkok(sd); - clif_movechar(sd); - if(dx < 0) dx = -dx; - if(dy < 0) dy = -dy; - sd->attackabletime = sd->canmove_tick = tick + 100 + sd->speed * ((dx > dy)? dx:dy); - if(sd->canact_tick < sd->canmove_tick) - sd->canact_tick = sd->canmove_tick; - pc_movepos(sd,sd->to_x,sd->to_y); - skill_status_change_end(&sd->bl,SC_COMBO,-1); - } - else - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - skill_status_change_end(src, SC_EXPLOSIONSPIRITS, -1); - if(sc_data && sc_data[SC_BLADESTOP].timer != -1) - skill_status_change_end(src,SC_BLADESTOP,-1); + else + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + status_change_end(src, SC_EXPLOSIONSPIRITS, -1); + if (sc_data && sc_data[SC_BLADESTOP].timer != -1) + status_change_end(src,SC_BLADESTOP,-1); } break; + /* •ŠíŒn”Í?U?ƒXƒLƒ‹ */ case AC_SHOWER: /* ƒAƒ?ƒVƒƒƒ? */ - case SM_MAGNUM: /* ƒ}ƒOƒiƒ€ƒuƒŒƒCƒN */ case AS_GRIMTOOTH: /* ƒOƒŠƒ€ƒgƒD?ƒX */ case MC_CARTREVOLUTION: /* ƒJ?ƒgƒŒƒ”ƒHƒŠƒ…?ƒVƒ‡ƒ“ */ case NPC_SPLASHATTACK: /* ƒXƒvƒ‰ƒbƒVƒ…ƒAƒ^ƒbƒN */ - case ASC_METEORASSAULT: /* ƒƒeƒIƒAƒTƒ‹ƒg */ case AS_SPLASHER: /* [Valaris] */ if(flag&1){ /* ŒÂ•ʂɃ_ƒ?ƒW‚ð?‚¦‚é */ if(bl->id!=skill_area_temp[1]){ - int dist=0; - if(skillid==SM_MAGNUM){ /* ƒ}ƒOƒiƒ€ƒuƒŒƒCƒN‚Ȃ璆S‚©‚ç‚Ì‹——£‚ðŒvŽZ */ - int dx=abs( bl->x - skill_area_temp[2] ); - int dy=abs( bl->y - skill_area_temp[3] ); - dist=((dx>dy)?dx:dy); - } skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick, - 0x0500|dist ); + 0x0500); } - }else{ - int ar=1; - int x=bl->x,y=bl->y; - if( skillid==SM_MAGNUM){ - x=src->x; - y=src->y; - }else if(skillid==AC_SHOWER || skillid==ASC_METEORASSAULT) /* ƒAƒ?ƒVƒƒƒ?AƒƒeƒIƒAƒTƒ‹ƒg”Í?5*5 */ - ar=2; - else if(skillid==AS_SPLASHER) /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ?”Í?3*3 */ - ar=1; - else if(skillid==NPC_SPLASHATTACK) /* ƒXƒvƒ‰ƒbƒVƒ…ƒAƒ^ƒbƒN‚Í”Í?7*7 */ - ar=3; - - // meteor assault cast effect (not sure how else to properly add it =p) [Celest] - if (skillid == ASC_METEORASSAULT) - clif_specialeffect(&sd->bl,409, 1); - + } else { + int ar = 1; + int x = bl->x, y = bl->y; + switch (skillid) { + case AC_SHOWER: + ar=2; + break; + case NPC_SPLASHATTACK: + ar=3; + break; + } + skill_area_temp[1]=bl->id; skill_area_temp[2]=x; skill_area_temp[3]=y; @@ -2502,13 +2375,24 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s bl->m,x-ar,y-ar,x+ar,y+ar,0, src,skillid,skilllv,tick, flag|BCT_ENEMY|1, skill_castend_damage_id); - if (skillid == SM_MAGNUM) // fire element for 10 seconds - skill_status_change_start(src,SC_FLAMELAUNCHER,0,0,0,0,10000,0); } - if (bl->type == BL_MOB && skillid == AS_GRIMTOOTH) { - struct status_change *sc_data = battle_get_sc_data(bl); - if (sc_data && sc_data[SC_SLOWDOWN].timer == -1) - skill_status_change_start(bl,SC_SLOWDOWN,0,0,0,0,1000,0); + break; + + case SM_MAGNUM: /* ƒ}ƒOƒiƒ€ƒuƒŒƒCƒN [celest] */ + if(flag&1 && bl->id != skill_area_temp[1]){ + int dist = distance (bl->x, bl->y, skill_area_temp[2], skill_area_temp[3]); + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick, + 0x0500|dist); + } else { + skill_area_temp[1]=src->id; + skill_area_temp[2]=src->x; + skill_area_temp[3]=src->y; + map_foreachinarea(skill_area_sub, + src->m,src->x-2,src->y-2,src->x+2,src->y+2,0, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); + status_change_start (src,SC_FLAMELAUNCHER,0,0,0,0,10000,0); + clif_skill_nodamage (src,src,skillid,skilllv,1); } break; @@ -2517,13 +2401,11 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s /* ŒÂ•ʂɃ_ƒ?ƒW‚ð?‚¦‚é */ if(bl->id!=skill_area_temp[1]) skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500); - } - else { - int damage; - map_freeblock_lock(); - damage = skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0); - if(damage > 0) { + } else { int i,c; /* ‘¼l‚©‚ç•·‚¢‚½“®‚«‚Ȃ̂ŊԈá‚Á‚Ä‚é‰Â”\«‘å•?—¦‚ª?‚¢‚Á‚·„ƒ */ + /* ‚Ü‚¸ƒ^[ƒQƒbƒg‚ÉUŒ‚‚ð‰Á‚¦‚é */ + if (!skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0)) + break; c = skill_get_blewcount(skillid,skilllv); if(map[bl->m].flag.gvg) c = 0; for(i=0;i<c;i++){ @@ -2542,24 +2424,42 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s if(skill_area_temp[0]>1) break; } skill_area_temp[1]=bl->id; - skill_area_temp[2]=bl->x; - skill_area_temp[3]=bl->y; /* ‚»‚ÌŒãƒ^?ƒQƒbƒgˆÈŠO‚Ì”Í??‚Ì“G‘S?‚É?—‚ðs‚¤ */ map_foreachinarea(skill_area_sub, bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0, src,skillid,skilllv,tick, flag|BCT_ENEMY|1, skill_castend_damage_id); - battle_damage(src,bl,damage,1); - if(rdamage > 0) - battle_damage(bl,src,rdamage,0); + } + break; + + case KN_SPEARSTAB: /* ƒXƒsƒAƒXƒ^ƒu */ + if(flag&1){ + /* ŒÂ•ʂɃ_ƒ[ƒW‚ð—^‚¦‚é */ + if (bl->id==skill_area_temp[1]) + break; + if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500)) + skill_blown(src,bl,skill_area_temp[2]); + } else { + int x=bl->x,y=bl->y,i,dir; + /* ‚Ü‚¸ƒ^[ƒQƒbƒg‚ÉUŒ‚‚ð‰Á‚¦‚é */ + dir = map_calc_dir(bl,src->x,src->y); + skill_area_temp[1] = bl->id; + skill_area_temp[2] = skill_get_blewcount(skillid,skilllv)|dir<<20; + if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0)) + skill_blown(src,bl,skill_area_temp[2]); + for (i=0;i<4;i++) { + map_foreachinarea(skill_area_sub,bl->m,x,y,x,y,0, + src,skillid,skilllv,tick,flag|BCT_ENEMY|1, + skill_castend_damage_id); + x += dirx[dir]; + y += diry[dir]; } - map_freeblock_unlock(); } break; case ALL_RESURRECTION: /* ƒŠƒUƒŒƒNƒVƒ‡ƒ“ */ case PR_TURNUNDEAD: /* ƒ^?ƒ“ƒAƒ“ƒfƒbƒh */ - if(bl->type != BL_PC && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) + if(bl->type != BL_PC && battle_check_undead(status_get_race(bl),status_get_elem_type(bl))) skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); else { map_freeblock_unlock(); @@ -2569,67 +2469,95 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s /* –‚–@ŒnƒXƒLƒ‹ */ case MG_SOULSTRIKE: /* ƒ\ƒEƒ‹ƒXƒgƒ‰ƒCƒN */ - case MG_COLDBOLT: /* ƒR?ƒ‹ƒhƒ{ƒ‹ƒg */ - case MG_FIREBOLT: /* ƒtƒ@ƒCƒA?ƒ{ƒ‹ƒg */ + case NPC_DARKSOULSTRIKE: /*ˆÅƒ\ƒEƒ‹ƒXƒgƒ‰ƒCƒN*/ + case MG_COLDBOLT: /* ƒR[ƒ‹ƒhƒ{ƒ‹ƒg */ + case MG_FIREBOLT: /* ƒtƒ@ƒCƒA[ƒ{ƒ‹ƒg */ case MG_LIGHTNINGBOLT: /* ƒ‰ƒCƒgƒjƒ“ƒOƒ{ƒ‹ƒg */ - case WZ_EARTHSPIKE: /* ƒA?ƒXƒXƒpƒCƒN */ - case AL_HEAL: /* ƒq?ƒ‹ */ - case AL_HOLYLIGHT: /* ƒz?ƒŠ?ƒ‰ƒCƒg */ - case MG_FROSTDIVER: /* ƒtƒƒXƒgƒ_ƒCƒo? */ - case WZ_JUPITEL: /* ƒ†ƒsƒeƒ‹ƒTƒ“ƒ_? */ + case WZ_EARTHSPIKE: /* ƒA[ƒXƒXƒpƒCƒN */ + case AL_HEAL: /* ƒq[ƒ‹ */ + case AL_HOLYLIGHT: /* ƒz[ƒŠ[ƒ‰ƒCƒg */ + case WZ_JUPITEL: /* ƒ†ƒsƒeƒ‹ƒTƒ“ƒ_[ */ + case NPC_DARKJUPITEL: /*ˆÅƒ†ƒsƒeƒ‹*/ case NPC_MAGICALATTACK: /* MOB:–‚–@‘Å?U? */ case PR_ASPERSIO: /* ƒAƒXƒyƒ‹ƒVƒI */ -// case HW_NAPALMVULCAN: /* ƒiƒp[ƒ€ƒoƒ‹ƒJƒ“ */ + case MG_FROSTDIVER: /* ƒtƒƒXƒgƒ_ƒCƒo[ */ skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); break; case WZ_WATERBALL: /* ƒEƒH?ƒ^?ƒ{?ƒ‹ */ skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - if(skilllv>1) - skill_status_change_start(src,SC_WATERBALL,skilllv,bl->id,0,0,0,0); + if (skilllv>1) { + int cnt,range; + range = skilllv>5?2:skilllv/2; + if (sd) + cnt = skill_count_water(src,range)-1; + else + cnt = skill_get_num(skillid,skilllv)-1; + if (cnt>0) + skill_addtimerskill(src,tick+150,bl->id,0,0, + skillid,skilllv,cnt,flag); + } break; case PR_BENEDICTIO: /* ¹?~•Ÿ */ - if(battle_get_race(bl)==1 || battle_get_race(bl)==6) + if(status_get_race(bl)==1 || status_get_race(bl)==6) skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); break; /* –‚–@Œn”Í?U?ƒXƒLƒ‹ */ case MG_NAPALMBEAT: /* ƒiƒp?ƒ€ƒr?ƒg */ case MG_FIREBALL: /* ƒtƒ@ƒCƒ„?ƒ{?ƒ‹ */ - if(flag&1){ + case WZ_SIGHTRASHER: /* ƒTƒCƒgƒ‰ƒbƒVƒƒ[ */ + if (flag & 1) { /* ŒÂ•ʂɃ_ƒ?ƒW‚ð?‚¦‚é */ - if(bl->id!=skill_area_temp[1]){ - if(skillid==MG_FIREBALL){ /* ƒtƒ@ƒCƒ„?ƒ{?ƒ‹‚Ȃ璆S‚©‚ç‚Ì‹——£‚ðŒvŽZ */ - int dx=abs( bl->x - skill_area_temp[2] ); - int dy=abs( bl->y - skill_area_temp[3] ); - skill_area_temp[0]=((dx>dy)?dx:dy); + if (bl->id != skill_area_temp[1]){ + if(skillid == MG_FIREBALL){ /* ƒtƒ@ƒCƒ„?ƒ{?ƒ‹‚Ȃ璆S‚©‚ç‚Ì‹——£‚ðŒvŽZ */ + skill_area_temp[0] = distance(bl->x, bl->y, skill_area_temp[2], skill_area_temp[3]); } skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick, skill_area_temp[0]| 0x0500); } - }else{ - int ar=(skillid==MG_NAPALMBEAT)?1:2; + } else { + int ar; + skill_area_temp[0]=0; skill_area_temp[1]=bl->id; - if(skillid==MG_NAPALMBEAT){ /* ƒiƒp?ƒ€‚Å‚Íæ‚É?‚¦‚é */ - skill_area_temp[0]=0; - map_foreachinarea(skill_area_sub, - bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY , - skill_area_sub_count); - }else{ - skill_area_temp[0]=0; - skill_area_temp[2]=bl->x; - skill_area_temp[3]=bl->y; + switch (skillid) { + case MG_NAPALMBEAT: + ar = 1; + /* ƒiƒp[ƒ€ƒr[ƒg‚Í•ªŽUƒ_ƒ[ƒW‚Ȃ̂œG‚Ì”‚𔂦‚é */ + map_foreachinarea(skill_area_sub, + bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0, + src,skillid,skilllv,tick,flag|BCT_ENEMY, + skill_area_sub_count); + break; + case MG_FIREBALL: + ar = 2; + skill_area_temp[2]=bl->x; + skill_area_temp[3]=bl->y; + /* ƒ^[ƒQƒbƒg‚ÉUŒ‚‚ð‰Á‚¦‚é(ƒXƒLƒ‹ƒGƒtƒFƒNƒg•\ަ) */ + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick, + skill_area_temp[0]); + break; + case WZ_SIGHTRASHER: + default: + ar = 3; + bl = src; + status_change_end(src,SC_SIGHT,-1); + break; } - /* ‚Ü‚¸ƒ^?ƒQƒbƒg‚ÉU?‚ð‰Á‚¦‚é */ - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick, - skill_area_temp[0] ); - /* ‚»‚ÌŒãƒ^?ƒQƒbƒgˆÈŠO‚Ì”Í??‚Ì“G‘S?‚É?—‚ðs‚¤ */ + if (skillid==WZ_SIGHTRASHER) { + /* ƒXƒLƒ‹ƒGƒtƒFƒNƒg•\ަ */ + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } else { + /* ƒ^[ƒQƒbƒg‚ÉUŒ‚‚ð‰Á‚¦‚é(ƒXƒLƒ‹ƒGƒtƒFƒNƒg•\ަ) */ + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick, + skill_area_temp[0]); + } + /* ƒ^[ƒQƒbƒgˆÈŠO‚͈͓̔à‚Ì“G‘S‘̂Ɉ—‚ðs‚¤ */ map_foreachinarea(skill_area_sub, - bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); + bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); } break; @@ -2663,15 +2591,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s break; case WZ_FROSTNOVA: /* ƒtƒƒXƒgƒmƒ”ƒ@ */ - skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0); - //skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - map_foreachinarea(skill_attack_area,src->m,src->x-5,bl->y-5,bl->x+5,bl->y+5,0,BF_MAGIC,src,src,skillid,skilllv,tick,flag,BCT_ENEMY); - break; - - case WZ_SIGHTRASHER: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0); - skill_status_change_end(src,SC_SIGHT,-1); + map_foreachinarea(skill_attack_area,src->m,src->x-5,bl->y-5,bl->x+5,bl->y+5,0,BF_MAGIC,src,src,skillid,skilllv,tick,flag,BCT_ENEMY); break; /* ‚»‚Ì‘¼ */ @@ -2697,6 +2617,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s break; case CR_GRANDCROSS: /* ƒOƒ‰ƒ“ƒhƒNƒƒX */ + case NPC_DARKGRANDCROSS: /*ˆÅƒOƒ‰ƒ“ƒhƒNƒƒX*/ /* ƒXƒLƒ‹ƒ†ƒjƒbƒg”z’u */ skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0); if(sd) @@ -2710,6 +2631,32 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,0 ); break; + // Celest + case PF_SOULBURN: + { + int per = skilllv < 5 ? 20+ skilllv*10 : 60; + if (rand()%100 < per) { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if (skilllv == 5) + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,0 ); + if (tsd && (map[src->m].flag.pvp || map[src->m].flag.gvg)) { + tsd->status.sp = 0; + clif_updatestatus(tsd,SP_SP); + } + } else { + clif_skill_nodamage(src,src,skillid,skilllv,1); + if (skilllv == 5) + skill_attack(BF_MAGIC,src,src,src,skillid,skilllv,tick,0 ); + if (sd) { + sd->status.sp = 0; + clif_updatestatus(sd,SP_SP); + } + } + if (sd) + pc_blockskill_start (sd, skillid, (skilllv < 5 ? 10000: 15000)); + } + break; + case NPC_SELFDESTRUCTION: /* Ž©”š */ case NPC_SELFDESTRUCTION2: /* Ž©”š2 */ if(flag&1){ @@ -2726,7 +2673,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s struct mob_data *md; if((md=(struct mob_data *)src)){ skill_area_temp[1]=bl->id; - skill_area_temp[2]=battle_get_hp(src); + skill_area_temp[2]=status_get_hp(src); clif_skill_nodamage(src,src,NPC_SELFDESTRUCTION,-1,1); map_foreachinarea(skill_area_sub, bl->m,bl->x-5,bl->y-5,bl->x+5,bl->y+5,0, @@ -2754,6 +2701,14 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s } } break; + + // unknown skills [Celest] + case NPC_BIND: + case NPC_EXPLOSIONSPIRITS: + case NPC_INCAGI: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + case 0: if(sd) { if(flag&3){ @@ -2772,12 +2727,13 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s break; default: + printf("Unknown skill used:%d\n",skillid); map_freeblock_unlock(); return 1; } if(sc_data) { if (sc_data[SC_MAGICPOWER].timer != -1 && skillid != HW_MAGICPOWER) //ƒ}ƒWƒbƒNƒpƒ?‚Ì?‰ÊI—¹ - skill_status_change_end(src,SC_MAGICPOWER,-1); + status_change_end(src,SC_MAGICPOWER,-1); } map_freeblock_unlock(); @@ -2788,107 +2744,96 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s * ƒXƒLƒ‹Žg—pi‰r¥Š®—¹AIDŽw’èŽx‰‡Œnj *------------------------------------------ */ -int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag ) +int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, int skillid, int skilllv, unsigned int tick, int flag) { - struct map_session_data *sd=NULL; - struct map_session_data *dstsd=NULL; - struct mob_data *md=NULL; - struct mob_data *dstmd=NULL; - int i,abra_skillid=0,abra_skilllv; - int sc_def_vit,sc_def_mdef,strip_fix,strip_time,strip_per; - int sc_dex,sc_luk; - //ƒNƒ‰ƒXƒ`ƒFƒ“ƒW—pƒ{ƒXƒ‚ƒ“ƒXƒ^?ID - int changeclass[]={1038,1039,1046,1059,1086,1087,1112,1115 - ,1157,1159,1190,1272,1312,1373,1492}; - int poringclass[]={1002}; - - if(skilllv <= 0) return 0; + struct map_session_data *sd = NULL; + struct map_session_data *dstsd = NULL; + struct mob_data *md = NULL; + struct mob_data *dstmd = NULL; + int i; + int sc_def_vit, sc_def_mdef; + int sc_dex, sc_luk; + + if(skillid < 0) + { // remove the debug print when this case is finished + printf("skill_castend_damage_id: skillid=%i\ncall: %p %p %i %i %i %i",skillid, + src, bl,skillid,skilllv,tick,flag); + return 0; + } + if(skillid > 0 && skilllv <= 0) return 0; // celest nullpo_retr(1, src); nullpo_retr(1, bl); - if(src->type==BL_PC) - sd=(struct map_session_data *)src; - else if(src->type==BL_MOB) - md=(struct mob_data *)src; - - sc_dex=battle_get_mdef(bl); - sc_luk=battle_get_luk(bl); - sc_def_vit = 100 - (3 + battle_get_vit(bl) + battle_get_luk(bl)/3); - //sc_def_vit = 100 - (3 + battle_get_vit(bl) + battle_get_luk(bl)/3); - sc_def_mdef = 100 - (3 + battle_get_mdef(bl) + battle_get_luk(bl)/3); - strip_fix = battle_get_dex(src) - battle_get_dex(bl); - - if(bl->type==BL_PC){ - nullpo_retr(1, dstsd=(struct map_session_data *)bl); - }else if(bl->type==BL_MOB){ - nullpo_retr(1, dstmd=(struct mob_data *)bl); - if(sc_def_vit>50) - sc_def_vit=50; - if(sc_def_mdef>50) - sc_def_mdef=50; - } - if(sc_def_vit < 0) - sc_def_vit=0; - if(sc_def_mdef < 0) - sc_def_mdef=0; - if(strip_fix < 0) - strip_fix=0; - - if(bl == NULL || bl->prev == NULL) + if (src->type == BL_PC) { + nullpo_retr (1, sd = (struct map_session_data *)src); + } else if (src->type == BL_MOB) { + nullpo_retr (1, md = (struct mob_data *)src); + } + + sc_dex = status_get_mdef (bl); + sc_luk = status_get_luk (bl); + sc_def_vit = status_get_sc_def_vit (bl); + sc_def_mdef = status_get_sc_def_mdef (bl); + + if (bl->type == BL_PC){ + nullpo_retr (1, dstsd = (struct map_session_data *)bl); + } else if (bl->type == BL_MOB){ + nullpo_retr (1, dstmd = (struct mob_data *)bl); + } + + if(bl->prev == NULL) return 1; if(sd && pc_isdead(sd)) return 1; if(dstsd && pc_isdead(dstsd) && skillid != ALL_RESURRECTION) return 1; - if(battle_get_class(bl) == 1288) + if(status_get_class(bl) == 1288) return 1; - if (skillnotok(skillid, (struct map_session_data *)bl)) // [MouseJstr] + if (sd && skillnotok(skillid, sd)) // [MouseJstr] return 0; - + map_freeblock_lock(); switch(skillid) { case AL_HEAL: /* ƒq?ƒ‹ */ { - int heal=skill_calc_heal( src, skilllv ); + int heal = skill_calc_heal(src, skilllv); int heal_get_jobexp; int skill; - struct pc_base_job s_class; - if( dstsd && dstsd->special_state.no_magic_damage ) + if (skilllv > 10) + heal = 9999; //9999ƒq[ƒ‹ + if (dstsd && dstsd->special_state.no_magic_damage) heal=0; /* ?‹à峃J?ƒhiƒq?ƒ‹—Ê‚Oj */ - if (sd){ - s_class = pc_calc_base_job(sd->status.class); - if((skill=pc_checkskill(sd,HP_MEDITATIO))>0) // ƒƒfƒBƒeƒCƒeƒBƒI - heal += heal*skill*2/100; - if(sd && dstsd && sd->status.partner_id == dstsd->status.char_id && s_class.job == 23 && sd->status.sex == 0) //Ž©•ª‚à?Û‚àPCA?Û‚ªŽ©•ª‚̃p?ƒgƒi?AŽ©•ª‚ªƒXƒpƒmƒrAŽ©•ª‚ªŠ‚È‚ç + if (sd) { + if ((skill = pc_checkskill(sd, HP_MEDITATIO)) > 0) // ƒƒfƒBƒeƒCƒeƒBƒI + heal += heal * skill * 2 / 100; + if (sd && dstsd && sd->status.partner_id == dstsd->status.char_id && + pc_calc_base_job2(sd->status.class_) == 23 && sd->status.sex == 0) //Ž©•ª‚à?Û‚àPCA?Û‚ªŽ©•ª‚̃p?ƒgƒi?AŽ©•ª‚ªƒXƒpƒmƒrAŽ©•ª‚ªŠ‚È‚ç heal = heal*2; //ƒXƒpƒmƒr‚̉łª’U“߂Ƀq?ƒ‹‚·‚邯2”{‚ɂȂé } - - clif_skill_nodamage(src,bl,skillid,heal,1); + clif_skill_nodamage (src, bl, skillid, heal, 1); heal_get_jobexp = battle_heal(NULL,bl,heal,0,0); // JOB??’lŠl“¾ - if(src->type == BL_PC && bl->type==BL_PC && heal > 0 && src != bl && battle_config.heal_exp > 0){ + if(sd && dstsd && heal > 0 && sd != dstsd && battle_config.heal_exp > 0){ heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100; - if(heal_get_jobexp <= 0) + if (heal_get_jobexp <= 0) heal_get_jobexp = 1; - pc_gainexp((struct map_session_data *)src,0,heal_get_jobexp); + pc_gainexp (sd, 0, heal_get_jobexp); } } break; case ALL_RESURRECTION: /* ƒŠƒUƒŒƒNƒVƒ‡ƒ“ */ - if(bl->type==BL_PC){ - int per=0; - struct map_session_data *tsd = (struct map_session_data*)bl; - nullpo_retr(1, tsd); - if( (map[bl->m].flag.pvp) && tsd->pvp_point<0 ) + if(dstsd) { + int per = 0; + if (map[bl->m].flag.pvp && dstsd->pvp_point < 0) break; /* PVP‚Å•œŠˆ•s‰Â”\?‘Ô */ - if(pc_isdead(tsd)){ /* Ž€–S”»’è */ + if (pc_isdead(dstsd)) { /* Ž€–S”»’è */ clif_skill_nodamage(src,bl,skillid,skilllv,1); switch(skilllv){ case 1: per=10; break; @@ -2896,139 +2841,153 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case 3: per=50; break; case 4: per=80; break; } - tsd->status.hp=tsd->status.max_hp*per/100; - if(tsd->status.hp<=0) tsd->status.hp=1; - if(tsd->special_state.restart_full_recover ){ /* ƒIƒVƒŠƒXƒJ?ƒh */ - tsd->status.hp=tsd->status.max_hp; - tsd->status.sp=tsd->status.max_sp; + dstsd->status.hp = dstsd->status.max_hp * per / 100; + if (dstsd->status.hp <= 0) dstsd->status.hp = 1; + if (dstsd->special_state.restart_full_recover) { /* ƒIƒVƒŠƒXƒJ?ƒh */ + dstsd->status.hp = dstsd->status.max_hp; + dstsd->status.sp = dstsd->status.max_sp; } - pc_setstand(tsd); + pc_setstand(dstsd); if(battle_config.pc_invincible_time > 0) - pc_setinvincibletimer(tsd,battle_config.pc_invincible_time); - clif_updatestatus(tsd,SP_HP); - clif_resurrection(&tsd->bl,1); - if(src != bl && sd && battle_config.resurrection_exp > 0) { + pc_setinvincibletimer(dstsd, battle_config.pc_invincible_time); + clif_updatestatus(dstsd, SP_HP); + clif_resurrection(bl, 1); + if(sd && sd != dstsd && battle_config.resurrection_exp > 0) { int exp = 0,jexp = 0; - int lv = tsd->status.base_level - sd->status.base_level, jlv = tsd->status.job_level - sd->status.job_level; + int lv = dstsd->status.base_level - sd->status.base_level, jlv = dstsd->status.job_level - sd->status.job_level; if(lv > 0) { - exp = (int)((double)tsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); - if(exp < 1) exp = 1; + exp = (int)((double)dstsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); + if (exp < 1) exp = 1; } if(jlv > 0) { - jexp = (int)((double)tsd->status.job_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); - if(jexp < 1) jexp = 1; + jexp = (int)((double)dstsd->status.job_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); + if (jexp < 1) jexp = 1; } if(exp > 0 || jexp > 0) - pc_gainexp(sd,exp,jexp); + pc_gainexp (sd, exp, jexp); } } } break; case AL_DECAGI: /* ‘¬“xŒ¸ */ - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + if (dstsd && dstsd->special_state.no_magic_damage) break; - if( rand()%100 < (50+skilllv*3+(battle_get_lv(src)+battle_get_int(src)/5)-sc_def_mdef) ) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0); + if (rand() % 100 < (50 + skilllv * 3 + (status_get_lv(src) + status_get_int(src) / 5) - sc_def_mdef)) { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + status_change_start (bl, SkillStatusChangeTable[skillid], skilllv, 0, 0, 0, skill_get_time(skillid,skilllv), 0); } break; case AL_CRUCIS: - if(flag&1) { - int race = battle_get_race(bl),ele = battle_get_elem_type(bl); - if(battle_check_target(src,bl,BCT_ENEMY) && (race == 6 || battle_check_undead(race,ele))) { - int slv=battle_get_lv(src),tlv=battle_get_lv(bl),rate; - rate = 25 + skilllv*2 + slv - tlv; - if(rand()%100 < rate) - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,0,0); + if (flag & 1) { + int race = status_get_race (bl), ele = status_get_elem_type (bl); + if (battle_check_target (src, bl, BCT_ENEMY) && (race == 6 || battle_check_undead (race, ele))) { + int slv = status_get_lv (src),tlv = status_get_lv (bl); + int rate = 25 + skilllv*2 + slv - tlv; + if (rand()%100 < rate) + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,0,0); } - } - else { - int range = 15; - clif_skill_nodamage(src,bl,skillid,skilllv,1); + } else { + clif_skill_nodamage(src, bl, skillid, skilllv, 1); map_foreachinarea(skill_area_sub, - src->m,src->x-range,src->y-range,src->x+range,src->y+range,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + src->m, src->x-15, src->y-15, src->x+15, src->y+15, 0, + src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); } break; case PR_LEXDIVINA: /* ƒŒƒbƒNƒXƒfƒBƒr?ƒi */ { - struct status_change *sc_data = battle_get_sc_data(bl); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + struct status_change *sc_data = status_get_sc_data(bl); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (dstsd && dstsd->special_state.no_magic_damage) break; - if(sc_data && sc_data[SC_DIVINA].timer != -1) - skill_status_change_end(bl,SC_DIVINA,-1); - else if( rand()%100 < sc_def_vit ) { - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0); + if (sc_data && sc_data[SC_DIVINA].timer != -1) + status_change_end(bl,SC_DIVINA, -1); + else if (rand() % 100 < sc_def_vit) { + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0); } } break; + case SA_ABRACADABRA: - //require 1 yellow gemstone even with mistress card or Into the Abyss - if ((i=pc_search_inventory(sd, 715)) < 0 ) { //bug fixed by Lupus (item pos can be 0, too!) - clif_skill_fail(sd,sd->skillid,0,0); - break; + { + int abra_skillid = 0, abra_skilllv; + //require 1 yellow gemstone even with mistress card or Into the Abyss + if ((i = pc_search_inventory(sd, 715)) < 0 ) { //bug fixed by Lupus (item pos can be 0, too!) + clif_skill_fail(sd,sd->skillid,0,0); + break; + } + pc_delitem(sd, i, 1, 0); + do { + abra_skillid = rand() % 331; + if (skill_abra_db[abra_skillid].req_lv > skilllv || + rand()%10000 >= skill_abra_db[abra_skillid].per || //db‚ɊŒƒxƒ‹?Šm—¦”»’è + (abra_skillid >= NPC_PIERCINGATT && abra_skillid <= NPC_SUMMONMONSTER) || //NPCƒXƒLƒ‹‚̓_ƒ + skill_get_unit_flag(abra_skillid) & UF_DANCE) //‰‰‘tƒXƒLƒ‹‚̓_ƒ + abra_skillid = 0; // reset to get a new id + } while (abra_skillid == 0); + abra_skilllv = skill_get_max(abra_skillid) > skilllv ? skilllv : skill_get_max(abra_skillid); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + sd->skillitem = abra_skillid; + sd->skillitemlv = abra_skilllv; + clif_item_skill (sd, abra_skillid, abra_skilllv, "Abracadabra"); } - //pc_delitem(sd, pc_search_inventory(sd, 715), 1, 0); - pc_delitem(sd, i, 1, 0); - // - do{ - abra_skillid=skill_abra_dataset(skilllv); - }while(abra_skillid == 0); - abra_skilllv=skill_get_max(abra_skillid)>pc_checkskill(sd,SA_ABRACADABRA)?pc_checkskill(sd,SA_ABRACADABRA):skill_get_max(abra_skillid); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - sd->skillitem=abra_skillid; - sd->skillitemlv=abra_skilllv; - clif_item_skill(sd,abra_skillid,abra_skilllv,"ƒAƒuƒ‰ƒJƒ_ƒuƒ‰"); break; + case SA_COMA: clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if(dstsd){ - dstsd->status.hp=1; - dstsd->status.sp=1; - clif_updatestatus(dstsd,SP_HP); - clif_updatestatus(dstsd,SP_SP); + if (dstsd) { + if (dstsd->special_state.no_magic_damage) + break; + dstsd->status.hp = 1; + dstsd->status.sp = 1; + clif_updatestatus(dstsd, SP_HP); + clif_updatestatus(dstsd, SP_SP); } - if(dstmd) dstmd->hp=1; + if(dstmd) dstmd->hp = 1; break; case SA_FULLRECOVERY: clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if(dstsd) pc_heal(dstsd,dstsd->status.max_hp,dstsd->status.max_sp); - if(dstmd) dstmd->hp=battle_get_max_hp(&dstmd->bl); + if (dstsd) { + if (dstsd->special_state.no_magic_damage) + break; + pc_heal (dstsd, dstsd->status.max_hp, dstsd->status.max_sp); + } + if (dstmd) dstmd->hp = status_get_max_hp(bl); break; case SA_SUMMONMONSTER: clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (sd) mob_once_spawn(sd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,"--ja--",-1,1,""); + if (sd) mob_once_spawn(sd,map[src->m].name,src->x,src->y,"--ja--",-1,1,""); break; case SA_LEVELUP: clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (sd && pc_nextbaseexp(sd)) pc_gainexp(sd,pc_nextbaseexp(sd)*10/100,0); + if (sd && pc_nextbaseexp(sd)) pc_gainexp(sd, pc_nextbaseexp(sd) * 10 / 100, 0); break; - case SA_INSTANTDEATH: clif_skill_nodamage(src,bl,skillid,skilllv,1); if (sd) pc_damage(NULL,sd,sd->status.max_hp); break; - case SA_QUESTION: case SA_GRAVITY: clif_skill_nodamage(src,bl,skillid,skilllv,1); break; case SA_CLASSCHANGE: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(dstmd) mob_class_change(dstmd,changeclass); + { + //ƒNƒ‰ƒXƒ`ƒFƒ“ƒW—pƒ{ƒXƒ‚ƒ“ƒXƒ^?ID + int changeclass[]={1038,1039,1046,1059,1086,1087,1112,1115 + ,1157,1159,1190,1272,1312,1373,1492}; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if(dstmd) mob_class_change(dstmd,changeclass); + } break; case SA_MONOCELL: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(dstmd) mob_class_change(dstmd,poringclass); + { + int poringclass[]={1002}; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if(dstmd) mob_class_change(dstmd,poringclass); + } break; case SA_DEATH: clif_skill_nodamage(src,bl,skillid,skilllv,1); @@ -3041,19 +3000,20 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int break; case SA_FORTUNE: clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(sd) pc_getzeny(sd,battle_get_lv(bl)*100); + if(sd) pc_getzeny(sd,status_get_lv(bl)*100); break; case SA_TAMINGMONSTER: clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (dstmd){ - for(i=0;i<MAX_PET_DB;i++){ - if(dstmd->class == pet_db[i].class){ - pet_catch_process1(sd,dstmd->class); + if (dstmd) { + for (i = 0; i < MAX_PET_DB; i++) { + if (dstmd->class_ == pet_db[i].class_) { + pet_catch_process1 (sd, dstmd->class_); break; } } } break; + case AL_INCAGI: /* ‘¬“x?‰Á */ case AL_BLESSING: /* ƒuƒŒƒbƒVƒ“ƒO */ case PR_SLOWPOISON: @@ -3062,38 +3022,37 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case PR_SUFFRAGIUM: /* ƒTƒtƒ‰ƒMƒEƒ€ */ case PR_BENEDICTIO: /* ¹?~•Ÿ */ case CR_PROVIDENCE: /* ƒvƒƒ”ƒBƒfƒ“ƒX */ - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ){ + if (dstsd && dstsd->special_state.no_magic_damage) clif_skill_nodamage(src,bl,skillid,skilllv,1); - }else{ - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + else { + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); clif_skill_nodamage(src,bl,skillid,skilllv,1); } break; case CG_MARIONETTE: /* ƒ}ƒŠƒIƒlƒbƒgƒRƒ“ƒgƒ?ƒ‹ */ - if(sd && dstsd){ - struct status_change *sc_data = battle_get_sc_data(src); - struct status_change *tsc_data = battle_get_sc_data(bl); + if (sd && dstsd){ + struct status_change *sc_data = status_get_sc_data(src); + struct status_change *tsc_data = status_get_sc_data(bl); int sc = SkillStatusChangeTable[skillid]; int sc2 = SC_MARIONETTE2; - - if((dstsd->bl.type!=BL_PC) - || (sd->bl.id == dstsd->bl.id) + + if ((sd == dstsd) || (!sd->status.party_id) - || (sd->status.party_id != dstsd->status.party_id)) { + || (sd->status.party_id != dstsd->status.party_id)) { clif_skill_fail(sd,skillid,0,0); map_freeblock_unlock(); return 1; } if(sc_data && tsc_data){ - if(sc_data[sc].timer == -1 && tsc_data[sc2].timer == -1) { - skill_status_change_start (src,sc,skilllv,0,bl->id,0,skill_get_time(skillid,skilllv),0); - skill_status_change_start (bl,sc2,skilllv,0,src->id,0,skill_get_time(skillid,skilllv),0); + if (sc_data[sc].timer == -1 && tsc_data[sc2].timer == -1) { + status_change_start (src,sc,skilllv,0,bl->id,0,skill_get_time(skillid,skilllv),0); + status_change_start (bl,sc2,skilllv,0,src->id,0,skill_get_time(skillid,skilllv),0); } else if (sc_data[sc].timer != -1 && tsc_data[sc2].timer != -1 && - sc_data[sc].val3 == bl->id && tsc_data[sc2].val3 == src->id) { - skill_status_change_end(src, sc, -1); - skill_status_change_end(bl, sc2, -1); + sc_data[sc].val3 == bl->id && tsc_data[sc2].val3 == src->id) { + status_change_end(src, sc, -1); + status_change_end(bl, sc2, -1); } else { clif_skill_fail(sd,skillid,0,0); @@ -3102,57 +3061,60 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int } clif_skill_nodamage(src,bl,skillid,skilllv,1); } - } + } break; case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris] case SA_FROSTWEAPON: case SA_LIGHTNINGLOADER: case SA_SEISMICWEAPON: - if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ){ - clif_skill_nodamage(src,bl,skillid,skilllv,0); - break; - } - if(bl->type==BL_PC) { - struct map_session_data *sd2=(struct map_session_data *)bl; - if(sd2->status.weapon==0 || sd2->sc_data[SC_FLAMELAUNCHER].timer!=-1 || sd2->sc_data[SC_FROSTWEAPON].timer!=-1 || - sd2->sc_data[SC_LIGHTNINGLOADER].timer!=-1 || sd2->sc_data[SC_SEISMICWEAPON].timer!=-1 || - sd2->sc_data[SC_ENCPOISON].timer!=-1) { - clif_skill_fail(sd,skillid,0,0); + if (dstsd) { + if (dstsd->special_state.no_magic_damage) { + clif_skill_nodamage(src,bl,skillid,skilllv,0); + break; + } + if(dstsd->status.weapon == 0 || + (sd && sd->status.party_id > 0 && sd->status.party_id != dstsd->status.party_id) || + dstsd->sc_data[SC_FLAMELAUNCHER].timer != -1 || + dstsd->sc_data[SC_FROSTWEAPON].timer != -1 || + dstsd->sc_data[SC_LIGHTNINGLOADER].timer != -1 || + dstsd->sc_data[SC_SEISMICWEAPON].timer != -1 || + dstsd->sc_data[SC_ENCPOISON].timer != -1) { + if (sd) clif_skill_fail(sd,skillid,0,0); clif_skill_nodamage(src,bl,skillid,skilllv,0); break; } } - if(rand()%100 > (75+skilllv*1) && (skilllv != 5)) { - clif_skill_fail(sd,skillid,0,0); + if(skilllv < 5 && rand()%100 > (60+skilllv*10) ) { //fixed by Lupus (4 -> 5) or else it has 100% success even at lv4 + if (sd) clif_skill_fail(sd,skillid,0,0); clif_skill_nodamage(src,bl,skillid,skilllv,0); - if(bl->type==BL_PC && battle_config.equipment_breaking) { - struct map_session_data *sd2=(struct map_session_data *)bl; - if(sd!=sd2) clif_displaymessage(sd->fd,"You broke target's weapon"); - pc_breakweapon(sd2); + if(dstsd && battle_config.equipment_breaking) { + if(sd && sd != dstsd) clif_displaymessage(sd->fd,"You broke target's weapon"); + pc_breakweapon(dstsd); } break; - } - else { - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + } else { + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); clif_skill_nodamage(src,bl,skillid,skilllv,1); } break; case PR_ASPERSIO: /* ƒAƒXƒyƒ‹ƒVƒI */ clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + if (dstsd && dstsd->special_state.no_magic_damage) break; - if(bl->type==BL_MOB) + if (dstmd) break; - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); break; + case PR_KYRIE: /* ƒLƒŠƒGƒGƒŒƒCƒ\ƒ“ */ clif_skill_nodamage(bl,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + if (dstsd && dstsd->special_state.no_magic_damage) break; - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); break; + case KN_AUTOCOUNTER: /* ƒI?ƒgƒJƒEƒ“ƒ^? */ case KN_TWOHANDQUICKEN: /* ƒc?ƒnƒ“ƒhƒNƒCƒbƒPƒ“ */ case CR_SPEARQUICKEN: /* ƒXƒsƒAƒNƒCƒbƒPƒ“ */ @@ -3176,68 +3138,87 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case ST_REJECTSWORD: /* ƒŠƒWƒFƒNƒgƒ\?ƒh */ case HW_MAGICPOWER: /* –‚–@—Í?• */ case PF_MEMORIZE: /* ƒƒ‚ƒ‰ƒCƒY */ + case PA_SACRIFICE: case ASC_EDP: // [Celest] + case CG_MOONLIT: /* ŒŽ–¾‚è‚Ìò‚É—Ž‚¿‚é‰Ô‚Ñ‚ç */ clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); break; + case SM_ENDURE: /* ƒCƒ“ƒfƒ…ƒA */ clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - skill_status_change_start(src,SC_BLOCKSKILL,skilllv,0,skillid,0,10000,0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + if (sd) + pc_blockskill_start (sd, skillid, 10000); break; - - + + case SM_AUTOBERSERK: // Celest + { + struct status_change *tsc_data = status_get_sc_data(bl); + int sc = SkillStatusChangeTable[skillid]; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if (tsc_data && tsc_data[sc].timer != -1) + status_change_end(bl, sc, -1); + else + status_change_start(bl,sc,skilllv,0,0,0,0,0); + } + break; + case AS_ENCHANTPOISON: // Prevent spamming [Valaris] - if(bl->type==BL_PC) { - struct map_session_data *sd2=(struct map_session_data *)bl; - if(sd2->sc_data[SC_FLAMELAUNCHER].timer!=-1 || sd2->sc_data[SC_FROSTWEAPON].timer!=-1 || - sd2->sc_data[SC_LIGHTNINGLOADER].timer!=-1 || sd2->sc_data[SC_SEISMICWEAPON].timer!=-1 || - sd2->sc_data[SC_ENCPOISON].timer!=-1) { - clif_skill_nodamage(src,bl,skillid,skilllv,0); - clif_skill_fail(sd,skillid,0,0); - break; + if (dstsd) { + if(dstsd->sc_data[SC_FLAMELAUNCHER].timer != -1 || + dstsd->sc_data[SC_FROSTWEAPON].timer != -1 || + dstsd->sc_data[SC_LIGHTNINGLOADER].timer != -1 || + dstsd->sc_data[SC_SEISMICWEAPON].timer != -1 || + dstsd->sc_data[SC_ENCPOISON].timer != -1) { + clif_skill_nodamage(src,bl,skillid,skilllv,0); + clif_skill_fail(sd,skillid,0,0); + break; } } clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); break; + case LK_TENSIONRELAX: /* ƒeƒ“ƒVƒ‡ƒ“ƒŠƒ‰ƒbƒNƒX */ clif_skill_nodamage(src,bl,skillid,skilllv,1); pc_setsit(sd); clif_sitting(sd); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); break; case LK_BERSERK: /* ƒo?ƒT?ƒN */ clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); //sd->status.hp = sd->status.max_hp * 3; break; + case MC_CHANGECART: clif_skill_nodamage(src,bl,skillid,skilllv,1); break; + case AC_CONCENTRATION: /* W’†—ÍŒüã */ { int range = 1; clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - map_foreachinarea( skill_status_change_timer_sub, + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + map_foreachinarea( status_change_timer_sub, src->m, src->x-range, src->y-range, src->x+range,src->y+range,0, src,SkillStatusChangeTable[skillid],tick); } break; + case SM_PROVOKE: /* ƒvƒƒ{ƒbƒN */ { - struct status_change *sc_data = battle_get_sc_data(bl); + struct status_change *sc_data = status_get_sc_data(bl); /* MVPmob‚Æ•sŽ€‚É‚Í?‚©‚È‚¢ */ - if((bl->type==BL_MOB && battle_get_mode(bl)&0x20) || battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) //•sŽ€‚É‚Í?‚©‚È‚¢ - { + if((dstmd && status_get_mode(bl)&0x20) || battle_check_undead(status_get_race(bl),status_get_elem_type(bl))) { //•sŽ€‚É‚Í?‚©‚È‚¢ map_freeblock_unlock(); return 1; } clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); if(dstmd && dstmd->skilltimer!=-1 && dstmd->state.skillcastcancel) // ‰r¥–WŠQ skill_castcancel(bl,0); @@ -3247,18 +3228,17 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int if(sc_data){ if(sc_data[SC_FREEZE].timer!=-1) - skill_status_change_end(bl,SC_FREEZE,-1); + status_change_end(bl,SC_FREEZE,-1); if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0) - skill_status_change_end(bl,SC_STONE,-1); + status_change_end(bl,SC_STONE,-1); if(sc_data[SC_SLEEP].timer!=-1) - skill_status_change_end(bl,SC_SLEEP,-1); + status_change_end(bl,SC_SLEEP,-1); } - if(bl->type==BL_MOB) { + if(dstmd) { int range = skill_get_range(skillid,skilllv); - if(range < 0) - range = battle_get_range(src) - (range + 1); - mob_target((struct mob_data *)bl,src,range); + dstmd->state.provoke_flag = src->id; + mob_target(dstmd,src,range); } } break; @@ -3266,27 +3246,27 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case CR_DEVOTION: /* ƒfƒBƒ{?ƒVƒ‡ƒ“ */ if(sd && dstsd){ //?¶‚â—{Žq‚Ìꇂ̌³‚ÌE‹Æ‚ðŽZo‚·‚é - struct pc_base_job dst_s_class = pc_calc_base_job(dstsd->status.class); - - int lv = sd->status.base_level-dstsd->status.base_level; - lv = (lv<0)?-lv:lv; - if((dstsd->bl.type!=BL_PC) // ‘ŠŽè‚ÍPC‚¶‚á‚È‚¢‚Æ‚¾‚ß - ||(sd->bl.id == dstsd->bl.id) // ‘ŠŽè‚ªŽ©•ª‚Í‚¾‚ß - ||(lv > 10) // ƒŒƒxƒ‹·}10‚܂Š- ||(!sd->status.party_id && !sd->status.guild_id) // PT‚É‚àƒMƒ‹ƒh‚É‚àŠ?–³‚µ‚Í‚¾‚ß - ||((sd->status.party_id != dstsd->status.party_id) // “¯‚¶ƒp?ƒeƒB?‚©A - &&(sd->status.guild_id != dstsd->status.guild_id)) // “¯‚¶ƒMƒ‹ƒh‚¶‚á‚È‚¢‚Æ‚¾‚ß - ||(dst_s_class.job==14||dst_s_class.job==21)){ // ƒNƒ‹ƒZ‚¾‚ß + int s_class = pc_calc_base_job2 (dstsd->status.class_); + + int lv = sd->status.base_level - dstsd->status.base_level; + if (lv < 0) lv = -lv; + if ((sd == dstsd) // ‘ŠŽè‚ÍPC‚¶‚á‚È‚¢‚Æ‚¾‚ß + || (sd->bl.id == dstsd->bl.id) // ‘ŠŽè‚ªŽ©•ª‚Í‚¾‚ß + || (lv > battle_config.devotion_level_difference) // ƒŒƒxƒ‹·}10‚܂Š+ || (!sd->status.party_id && !sd->status.guild_id) // PT‚É‚àƒMƒ‹ƒh‚É‚àŠ?–³‚µ‚Í‚¾‚ß + || ((sd->status.party_id != dstsd->status.party_id) // “¯‚¶ƒp?ƒeƒB?‚©A + &&(sd->status.guild_id != dstsd->status.guild_id)) // “¯‚¶ƒMƒ‹ƒh‚¶‚á‚È‚¢‚Æ‚¾‚ß + || (s_class == 14 || s_class == 21)) { // ƒNƒ‹ƒZ‚¾‚ß clif_skill_fail(sd,skillid,0,0); map_freeblock_unlock(); return 1; } - for(i=0;i<skilllv;i++){ - if(!sd->dev.val1[i]){ // ‹ó‚«‚ª‚ ‚Á‚½‚ç“ü‚ê‚é + for (i = 0; i < skilllv; i++) { + if (!sd->dev.val1[i]) { // ‹ó‚«‚ª‚ ‚Á‚½‚ç“ü‚ê‚é sd->dev.val1[i] = bl->id; sd->dev.val2[i] = bl->id; break; - }else if(i==skilllv-1){ // ‹ó‚«‚ª‚È‚©‚Á‚½ + } else if (i == skilllv - 1) { // ‹ó‚«‚ª‚È‚©‚Á‚½ clif_skill_fail(sd,skillid,0,0); map_freeblock_unlock(); return 1; @@ -3294,54 +3274,56 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int } clif_skill_nodamage(src,bl,skillid,skilllv,1); clif_devotion(sd,bl->id); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],src->id,1,0,0,1000*(15+15*skilllv),0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],src->id,1,0,0,1000*(15+15*skilllv),0 ); } - else clif_skill_fail(sd,skillid,0,0); + else clif_skill_fail(sd,skillid,0,0); break; + case MO_CALLSPIRITS: // ?Œ÷ if(sd) { clif_skill_nodamage(src,bl,skillid,skilllv,1); pc_addspiritball(sd,skill_get_time(skillid,skilllv),skilllv); } break; + case CH_SOULCOLLECT: // ‹¶?Œ÷ if(sd) { clif_skill_nodamage(src,bl,skillid,skilllv,1); - for(i=0;i<5;i++) + for (i = 0; i < 5; i++) pc_addspiritball(sd,skill_get_time(skillid,skilllv),5); } break; + case MO_BLADESTOP: // ”’nŽæ‚è clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); break; + case MO_ABSORBSPIRITS: // ?’D i=0; - if(sd && dstsd) { - if(sd == dstsd || map[sd->bl.m].flag.pvp || map[sd->bl.m].flag.gvg) { - if(dstsd->spiritball > 0) { + if (dstsd) { + if ((sd && sd == dstsd) || map[src->m].flag.pvp || map[src->m].flag.gvg) { + if (dstsd->spiritball > 0) { clif_skill_nodamage(src,bl,skillid,skilllv,1); i = dstsd->spiritball * 7; pc_delspiritball(dstsd,dstsd->spiritball,0); if(i > 0x7FFF) i = 0x7FFF; - if(sd->status.sp + i > sd->status.max_sp) + if(sd && sd->status.sp + i > sd->status.max_sp) i = sd->status.max_sp - sd->status.sp; - } + } } - }else if(sd && dstmd){ //?Û‚ªƒ‚ƒ“ƒXƒ^?‚Ìê‡ + } else if (dstmd) { //?Û‚ªƒ‚ƒ“ƒXƒ^?‚Ìê‡ //20%‚ÌŠm—¦‚Å?Û‚ÌLv*2‚ÌSP‚ð‰ñ•œ‚·‚éB¬Œ÷‚µ‚½‚Æ‚«‚̓^?ƒQƒbƒg(ƒÐ?„D?)ƒÐ????!! - if(rand()%100<20){ - i=2*mob_db[dstmd->class].lv; + if(rand() % 100 < 20) { + i = 2 * mob_db[dstmd->class_].lv; mob_target(dstmd,src,0); } } - if(i){ - sd->status.sp += i; - clif_heal(sd->fd,SP_SP,i); - } - else - clif_skill_nodamage(src,bl,skillid,skilllv,0); + if (i && sd){ + sd->status.sp += i; + clif_heal(sd->fd,SP_SP,i); + } else clif_skill_nodamage(src,bl,skillid,skilllv,0); break; case AC_MAKINGARROW: /* –îì¬ */ @@ -3375,29 +3357,30 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int clif_skill_produce_mix_list(sd,256); clif_skill_nodamage(src,bl,skillid,skilllv,1); } - break; + break; case BS_HAMMERFALL: /* ƒnƒ“ƒ}?ƒtƒH?ƒ‹ */ clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_weapon_damage ) + if(dstsd && dstsd->special_state.no_weapon_damage) break; - if( rand()%100 < (20+ 10*skilllv)*sc_def_vit/100 ) { - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - } + if(rand() % 100 < (20 + 10 * skilllv) * sc_def_vit / 100 ) + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case RG_RAID: /* ƒTƒvƒ‰ƒCƒYƒAƒ^ƒbƒN */ clif_skill_nodamage(src,bl,skillid,skilllv,1); - { - int x=bl->x,y=bl->y; - skill_area_temp[1]=bl->id; - skill_area_temp[2]=x; - skill_area_temp[3]=y; - map_foreachinarea(skill_area_sub, - bl->m,x-1,y-1,x+1,y+1,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - } - skill_status_change_end(src, SC_HIDING, -1); // ƒnƒCƒfƒBƒ“ƒO‰ðœ + map_foreachinarea(skill_area_sub, + bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); + status_change_end(src, SC_HIDING, -1); // ƒnƒCƒfƒBƒ“ƒO‰ðœ + break; + + case ASC_METEORASSAULT: /* ƒƒeƒIƒAƒTƒ‹ƒg */ + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinarea(skill_area_sub, + bl->m,bl->x-2,bl->y-2,bl->x+2,bl->y+2,0, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); break; case KN_BRANDISHSPEAR: /*ƒuƒ‰ƒ“ƒfƒBƒbƒVƒ…ƒXƒsƒA*/ @@ -3455,30 +3438,29 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case PR_MAGNIFICAT: /* ƒ}ƒOƒjƒtƒBƒJ?ƒg */ case PR_GLORIA: /* ƒOƒƒŠƒA */ case SN_WINDWALK: /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ - if(sd == NULL || sd->status.party_id==0 || (flag&1) ){ + if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) { /* ŒÂ•Ê‚Ì?— */ clif_skill_nodamage(bl,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + if(dstsd && dstsd->special_state.no_magic_damage) break; - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0); - } - else{ + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0); + } else if (sd) { /* ƒp?ƒeƒB‘S?‚Ö‚Ì?— */ - party_foreachsamemap(skill_area_sub, + party_foreachsamemap (skill_area_sub, sd,1, src,skillid,skilllv,tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); } break; + case BS_ADRENALINE: /* ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… */ case BS_WEAPONPERFECT: /* ƒEƒFƒ|ƒ“ƒp?ƒtƒFƒNƒVƒ‡ƒ“ */ case BS_OVERTHRUST: /* ƒI?ƒo?ƒgƒ‰ƒXƒg */ - if(sd == NULL || sd->status.party_id==0 || (flag&1) ){ + if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) { /* ŒÂ•Ê‚Ì?— */ clif_skill_nodamage(bl,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,(src == bl)? 1:0,0,0,skill_get_time(skillid,skilllv),0); - } - else{ + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,(src == bl)? 1:0,0,0,skill_get_time(skillid,skilllv),0); + } else if (sd) { /* ƒp?ƒeƒB‘S?‚Ö‚Ì?— */ party_foreachsamemap(skill_area_sub, sd,1, @@ -3493,66 +3475,54 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case CR_DEFENDER: /* ƒfƒBƒtƒFƒ“ƒ_? */ case CR_AUTOGUARD: /* ƒI?ƒgƒK?ƒh */ { - struct status_change *tsc_data = battle_get_sc_data(bl); - int sc=SkillStatusChangeTable[skillid]; + struct status_change *tsc_data = status_get_sc_data(bl); + int sc = SkillStatusChangeTable[skillid]; clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( tsc_data ){ - if( tsc_data[sc].timer==-1 ) - /* •t‰Á‚·‚é */ - skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0); - else - /* ‰ðœ‚·‚é */ - skill_status_change_end(bl, sc, -1); - } + if (tsc_data && tsc_data[sc].timer != -1) + status_change_end(bl, sc, -1); + else + status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0); } break; case TF_HIDING: /* ƒnƒCƒfƒBƒ“ƒO */ { - struct status_change *tsc_data = battle_get_sc_data(bl); - int sc=SkillStatusChangeTable[skillid]; + struct status_change *tsc_data = status_get_sc_data(bl); + int sc = SkillStatusChangeTable[skillid]; clif_skill_nodamage(src,bl,skillid,-1,1); - if( tsc_data ){ - if( tsc_data[sc].timer==-1 ) - /* •t‰Á‚·‚é */ - skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0); + if (tsc_data && tsc_data[sc].timer != -1) + status_change_end(bl, sc, -1); else - /* ‰ðœ‚·‚é */ - skill_status_change_end(bl, sc, -1); - } + status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0); } break; case AS_CLOAKING: /* ƒNƒ?ƒLƒ“ƒO */ { - struct status_change *tsc_data = battle_get_sc_data(bl); + struct status_change *tsc_data = status_get_sc_data(bl); int sc=SkillStatusChangeTable[skillid]; clif_skill_nodamage(src,bl,skillid,-1,1); - if( tsc_data ){ - if( tsc_data[sc].timer==-1 ) - /* •t‰Á‚·‚é */ - skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0); - else + if(tsc_data && tsc_data[sc].timer!=-1 ) /* ‰ðœ‚·‚é */ - skill_status_change_end(bl, sc, -1); - } + status_change_end(bl, sc, -1); + else + /* •t‰Á‚·‚é */ + status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0); //skill_check_cloaking(bl); } break; case ST_CHASEWALK: /* ƒnƒCƒfƒBƒ“ƒO */ { - struct status_change *tsc_data = battle_get_sc_data(bl); + struct status_change *tsc_data = status_get_sc_data(bl); int sc=SkillStatusChangeTable[skillid]; clif_skill_nodamage(src,bl,skillid,-1,1); - if( tsc_data ){ - if( tsc_data[sc].timer==-1 ) - /* •t‰Á‚·‚é */ - skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0); - else + if(tsc_data && tsc_data[sc].timer!=-1 ) /* ‰ðœ‚·‚é */ - skill_status_change_end(bl, sc, -1); - } + status_change_end(bl, sc, -1); + else + /* •t‰Á‚·‚é */ + status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0); } break; @@ -3575,32 +3545,20 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case DC_DONTFORGETME: /* Ž„‚ð–Y‚ê‚È‚¢‚Åc */ case DC_FORTUNEKISS: /* K‰^‚̃LƒX */ case DC_SERVICEFORYOU: /* ƒT?ƒrƒXƒtƒH?ƒ†? */ - case CG_MOONLIT: /* ŒŽ–¾‚è‚Ìò‚É—Ž‚¿‚é‰Ô‚Ñ‚ç */ +// case CG_MOONLIT: /* ŒŽ–¾‚è‚Ìò‚É—Ž‚¿‚é‰Ô‚Ñ‚ç */ clif_skill_nodamage(src,bl,skillid,skilllv,1); skill_unitsetting(src,skillid,skilllv,src->x,src->y,0); break; case HP_BASILICA: /* ƒoƒWƒŠƒJ */ { - // cancel Basilica if already in effect - struct status_change *sc_data = battle_get_sc_data(src); - if(sc_data && sc_data[SC_BASILICA].timer != -1){ - struct skill_unit *su; - if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) { - struct skill_unit_group *sg; - if ((sg = su->group) && sg->src_id == sd->bl.id) { - skill_status_change_end(src,SC_BASILICA,-1); - skill_delunitgroup (sg); - break; - } - } - } else { - // otherwise allow casting - skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0); - skill_clear_unitgroup(src); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_unitsetting(src,skillid,skilllv,src->x,src->y,0); - } + struct skill_unit_group *sg; + battle_stopwalking(src,1); + skill_clear_unitgroup(src); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0); + status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,(int)sg, + skill_get_time(skillid,skilllv),0); } break; @@ -3608,11 +3566,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int skill_clear_unitgroup(src); clif_skill_nodamage(src,bl,skillid,skilllv,1); skill_unitsetting(src,skillid,skilllv,src->x,src->y,0); + status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,BCT_SELF,skill_get_time(skillid,skilllv),0); break; case BD_ADAPTATION: /* ƒAƒhƒŠƒu */ { - struct status_change *sc_data = battle_get_sc_data(src); + struct status_change *sc_data = status_get_sc_data(src); if(sc_data && sc_data[SC_DANCING].timer!=-1){ clif_skill_nodamage(src,bl,skillid,skilllv,1); skill_stop_dancing(src,0); @@ -3636,11 +3595,11 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int break; case RG_STEALCOIN: // ƒXƒeƒB?ƒ‹ƒRƒCƒ“ - if(sd) { + if(sd) { if(pc_steal_coin(sd,bl)) { int range = skill_get_range(skillid,skilllv); if(range < 0) - range = battle_get_range(src) - (range + 1); + range = status_get_range(src) - (range + 1); clif_skill_nodamage(src,bl,skillid,skilllv,1); mob_target((struct mob_data *)bl,src,range); } @@ -3650,17 +3609,41 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int break; case MG_STONECURSE: /* ƒXƒg?ƒ“ƒJ?ƒX */ - if (bl->type==BL_MOB && battle_get_mode(bl)&0x20) { - clif_skill_fail(sd,sd->skillid,0,0); - break; + { + struct status_change *sc_data = status_get_sc_data(bl); + // Level 6-10 doesn't consume a red gem if it fails [celest] + int i, gem_flag = 1, fail_flag = 0; + if (dstmd && status_get_mode(bl)&0x20) { + clif_skill_fail(sd,sd->skillid,0,0); + break; + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if(dstsd && dstsd->special_state.no_magic_damage ) + break; + if (sc_data && sc_data[SC_STONE].timer != -1) { + status_change_end(bl,SC_STONE,-1); + if (sd) { + fail_flag = 1; + clif_skill_fail(sd,skillid,0,0); + } + } + else if( rand()%100 < skilllv*4+20 && !battle_check_undead(status_get_race(bl),status_get_elem_type(bl))) + status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + else if(sd) { + if (skilllv > 5) gem_flag = 0; + clif_skill_fail(sd,skillid,0,0); + fail_flag = 1; + } + if (dstmd) + mob_target(dstmd,src,skill_get_range(skillid,skilllv)); + if (sd && gem_flag) { + if ((i=pc_search_inventory(sd, skill_db[skillid].itemid[0])) < 0 ) { + if (!fail_flag) clif_skill_fail(sd,sd->skillid,0,0); + break; + } + pc_delitem(sd, i, skill_db[skillid].amount[0], 0); + } } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if( rand()%100 < skilllv*4+20 && !battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) - skill_status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - else if(sd) - clif_skill_fail(sd,skillid,0,0); break; case NV_FIRSTAID: /* ?‹}Žè? */ @@ -3670,37 +3653,36 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case AL_CURE: /* ƒLƒ…ƒA? */ clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + if(dstsd && dstsd->special_state.no_magic_damage ) break; - skill_status_change_end(bl, SC_SILENCE , -1 ); - skill_status_change_end(bl, SC_BLIND , -1 ); - skill_status_change_end(bl, SC_CONFUSION, -1 ); - if( battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) ){//ƒAƒ“ƒfƒbƒh‚È‚çˆÃˆÅ?‰Ê - skill_status_change_start(bl, SC_CONFUSION,1,0,0,0,6000,0); + status_change_end(bl, SC_SILENCE , -1 ); + status_change_end(bl, SC_BLIND , -1 ); + status_change_end(bl, SC_CONFUSION, -1 ); + if( battle_check_undead(status_get_race(bl),status_get_elem_type(bl)) ){//ƒAƒ“ƒfƒbƒh‚È‚çˆÃˆÅ?‰Ê + status_change_start(bl, SC_CONFUSION,1,0,0,0,6000,0); } break; case TF_DETOXIFY: /* ‰ð“Å */ clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_end(bl, SC_POISON , -1 ); - skill_status_change_end(bl, SC_DPOISON , -1 ); + status_change_end(bl, SC_POISON , -1 ); + status_change_end(bl, SC_DPOISON , -1 ); break; case PR_STRECOVERY: /* ƒŠƒJƒoƒŠ? */ { clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + if(dstsd && dstsd->special_state.no_magic_damage) break; - skill_status_change_end(bl, SC_FREEZE , -1 ); - skill_status_change_end(bl, SC_STONE , -1 ); - skill_status_change_end(bl, SC_SLEEP , -1 ); - skill_status_change_end(bl, SC_STAN , -1 ); - if( battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) ){//ƒAƒ“ƒfƒbƒh‚È‚çˆÃˆÅ?‰Ê - int blind_time; - //blind_time=30-battle_get_vit(bl)/10-battle_get_int/15; - blind_time=30*(100-(battle_get_int(bl)+battle_get_vit(bl))/2)/100; - if(rand()%100 < (100-(battle_get_int(bl)/2+battle_get_vit(bl)/3+battle_get_luk(bl)/10))) - skill_status_change_start(bl, SC_BLIND,1,0,0,0,blind_time,0); + status_change_end(bl, SC_FREEZE , -1 ); + status_change_end(bl, SC_STONE , -1 ); + status_change_end(bl, SC_SLEEP , -1 ); + status_change_end(bl, SC_STAN , -1 ); + if( battle_check_undead(status_get_race(bl),status_get_elem_type(bl)) ){//ƒAƒ“ƒfƒbƒh‚È‚çˆÃˆÅ?‰Ê + if(rand()%100 < (100-(status_get_int(bl)/2+status_get_vit(bl)/3+status_get_luk(bl)/10))) { + status_change_start(bl, SC_BLIND,1,0,0,0, + 1000 * 30 * (100-(status_get_int(bl)+status_get_vit(bl))/2)/100,0); + } } if(dstmd){ dstmd->attacked_id=0; @@ -3713,7 +3695,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int break; case WZ_ESTIMATION: /* ƒ‚ƒ“ƒXƒ^?î•ñ */ - if(src->type==BL_PC){ + if(sd) { clif_skill_nodamage(src,bl,skillid,skilllv,1); clif_skill_estimation((struct map_session_data *)src,bl); } @@ -3727,11 +3709,11 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case BS_REPAIRWEAPON: /* •ŠíC— */ if(sd) { //“®ì‚µ‚È‚¢‚Ì‚Å‚Æ‚è‚ ‚¦‚¸ƒRƒƒ“ƒgƒAƒEƒg - if (pc_search_inventory(sd, 999) < 0 ) { //fixed by Lupus (item pos can be = 0!) + /*if (pc_search_inventory(sd, 999) < 0 ) { //fixed by Lupus (item pos can be = 0!) clif_skill_fail(sd,sd->skillid,0,0); map_freeblock_unlock(); return 1; - } + }*/ clif_item_repair_list(sd); } break; @@ -3742,20 +3724,20 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int break; case AL_TELEPORT: /* ƒeƒŒƒ|?ƒg */ - if( sd ){ - if(map[sd->bl.m].flag.noteleport){ /* ƒeƒŒƒ|‹ÖŽ~ */ + if(sd) { + if (map[sd->bl.m].flag.noteleport) { /* ƒeƒŒƒ|‹ÖŽ~ */ clif_skill_teleportmessage(sd,0); break; } clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( sd->skilllv==1 ) + if(sd->skilllv == 1) clif_skill_warppoint(sd,sd->skillid,"Random","","",""); - else{ + else { clif_skill_warppoint(sd,sd->skillid,"Random", sd->status.save_point.map,"",""); } - }else if( bl->type==BL_MOB ) - mob_warp((struct mob_data *)bl,-1,-1,-1,3); + } else if(dstmd) + mob_warp(dstmd,-1,-1,-1,3); break; case AL_HOLYWATER: /* ƒAƒNƒAƒxƒlƒfƒBƒNƒ^ */ @@ -3799,136 +3781,102 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int break; case RG_STRIPWEAPON: /* ƒXƒgƒŠƒbƒvƒEƒFƒ|ƒ“ */ - { - struct status_change *tsc_data = battle_get_sc_data(bl); - - if(tsc_data && tsc_data[SC_CP_WEAPON].timer != -1 ) + case RG_STRIPSHIELD: /* ƒXƒgƒŠƒbƒvƒV[ƒ‹ƒh */ + case RG_STRIPARMOR: /* ƒXƒgƒŠƒbƒvƒA[ƒ}[ */ + case RG_STRIPHELM: /* ƒXƒgƒŠƒbƒvƒwƒ‹ƒ€ */ + { + struct status_change *tsc_data; + int strip_time, strip_per, strip_fix; + int scid, cp_scid = 0, equip; + + tsc_data = status_get_sc_data(bl); + scid = SkillStatusChangeTable[skillid]; + switch (skillid) { + case RG_STRIPWEAPON: + equip = EQP_WEAPON; + cp_scid = SC_CP_WEAPON; break; - strip_per = 5+2*skilllv+strip_fix/5; - strip_time = skill_get_time(skillid,skilllv)+strip_fix/2; - if(rand()%100 < strip_per){ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 ); - if(dstsd){ - for(i=0;i<MAX_INVENTORY;i++){ - if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0002){ - pc_unequipitem(dstsd,i,0,BF_SKILL); - break; - } - } - } - } - } - break; - - case RG_STRIPSHIELD: /* ƒXƒgƒŠƒbƒvƒV?ƒ‹ƒh */ - { - struct status_change *tsc_data = battle_get_sc_data(bl); - - if(tsc_data && tsc_data[SC_CP_SHIELD].timer != -1 ) + case RG_STRIPSHIELD: + equip = EQP_SHIELD; + cp_scid = SC_CP_SHIELD; break; - strip_per = 5+2*skilllv+strip_fix/5; - strip_time = skill_get_time(skillid,skilllv)+strip_fix/2; - if(rand()%100 < strip_per){ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 ); - if(dstsd){ - for(i=0;i<MAX_INVENTORY;i++){ - if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0020){ - pc_unequipitem(dstsd,i,0,BF_SKILL); - break; - } - } - } - } - } - break; - - case RG_STRIPARMOR: /* ƒXƒgƒŠƒbƒvƒA?ƒ}? */ - { - struct status_change *tsc_data = battle_get_sc_data(bl); - - if(tsc_data && tsc_data[SC_CP_ARMOR].timer != -1 ) + case RG_STRIPARMOR: + equip = EQP_ARMOR; + cp_scid = SC_CP_ARMOR; break; - strip_per = 5+2*skilllv+strip_fix/5; - strip_time = skill_get_time(skillid,skilllv)+strip_fix/2; - if(rand()%100 < strip_per){ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 ); - if(dstsd){ - for(i=0;i<MAX_INVENTORY;i++){ - if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0010){ - pc_unequipitem(dstsd,i,0,BF_SKILL); - break; - } - } - } - } - } - break; - - case RG_STRIPHELM: /* ƒXƒgƒŠƒbƒvƒwƒ‹ƒ€ */ - { - struct status_change *tsc_data = battle_get_sc_data(bl); - - if(tsc_data && tsc_data[SC_CP_HELM].timer != -1 ) + case RG_STRIPHELM: + equip = EQP_HELM; + cp_scid = SC_CP_HELM; break; - strip_per = 5+2*skilllv+strip_fix/5; - strip_time = skill_get_time(skillid,skilllv)+strip_fix/2; - if(rand()%100 < strip_per){ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 ); - if(dstsd){ - for(i=0;i<MAX_INVENTORY;i++){ - if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0100){ - pc_unequipitem(dstsd,i,0,BF_SKILL); - break; - } - } - } - } + default: + map_freeblock_unlock(); + return 1; } - break; - // Full Strip [Celest] - case ST_FULLSTRIP: - { - struct status_change *tsc_data = battle_get_sc_data(bl); - int c=0, i, j; - int striplist[2][4] = { { 0, 0, 0, 0 }, - { 0x0002, 0x0020, 0x0010, 0x0100 } }; + if (tsc_data && (tsc_data[scid].timer != -1 || tsc_data[cp_scid].timer != -1)) + break; + if (dstsd && dstsd->unstripable_equip & equip) + break; - strip_per = 5+2*skilllv+strip_fix/5; - strip_time = skill_get_time(skillid,skilllv)+strip_fix/2; - for (i=0; i<4; i++) { - if(tsc_data && tsc_data[SC_CP_WEAPON + i].timer != -1) + strip_fix = status_get_dex(src) - status_get_dex(bl); + if(strip_fix < 0) + strip_fix=0; + strip_per = 5+5*skilllv+strip_fix/5; + if (rand()%100 >= strip_per) + break; + + if (dstsd) { + for (i=0;i<MAX_INVENTORY;i++) { + if (dstsd->status.inventory[i].equip && (dstsd->status.inventory[i].equip & equip)){ + pc_unequipitem(dstsd,i,3); break; - if(rand()%100 < strip_per) { - striplist[0][i] = 1; - c++; } } - - if (c > 0) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - for (j=0; j<4 && c > 0; j++) { - if (striplist[0][j]) { - skill_status_change_start(bl,SC_STRIPWEAPON + i,skilllv,0,0,0,strip_time,0 ); - if(dstsd){ - for(i=0;i<MAX_INVENTORY;i++){ - if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & striplist[1][j]){ - pc_unequipitem(dstsd,i,0,BF_SKILL); - --c; - break; - } - } - } + if (i == MAX_INVENTORY) + break; + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + strip_time = skill_get_time(skillid,skilllv)+strip_fix/2; + status_change_start(bl,scid,skilllv,0,0,0,strip_time,0 ); + break; + } + case ST_FULLSTRIP: // Celest + { + struct status_change *tsc_data; + int i, j, strip_time, strip_per, strip_fix; + int equip[4] = { EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HELM }; + int scid[4] = { SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM }; + int cp_scid[4] = { SC_CP_WEAPON, SC_CP_SHIELD, SC_CP_ARMOR, SC_CP_HELM }; + + tsc_data = status_get_sc_data(bl); + strip_fix = status_get_dex(src) - status_get_dex(bl); + if(strip_fix < 0) + strip_fix = 0; + strip_per = 5+5*skilllv+strip_fix/5; + if (rand()%100 >= strip_per) + break; + strip_time = skill_get_time(skillid,skilllv)+strip_fix/2; + + for (i=0; i<4; i++) { + if (dstsd) { + if (tsc_data && (tsc_data[scid[i]].timer != -1 || tsc_data[cp_scid[i]].timer != -1)) + continue; + if (dstsd->unstripable_equip & equip[i]) + continue; + for (j=0; j<MAX_INVENTORY; j++) { + if (dstsd->status.inventory[j].equip && (dstsd->status.inventory[j].equip & equip[i])){ + pc_unequipitem(dstsd,j,3); + break; } } + if (j == MAX_INVENTORY) + continue; } + status_change_start(bl,scid[i],skilllv,0,0,0,strip_time,0 ); } + clif_skill_nodamage(src,bl,skillid,skilllv,1); break; - + } /* PotionPitcher */ case AM_POTIONPITCHER: /* ƒ|?ƒVƒ‡ƒ“ƒsƒbƒ`ƒƒ? */ @@ -3936,10 +3884,6 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int struct block_list tbl; int i,x,hp = 0,sp = 0; if(sd) { - if(sd==dstsd) { // cancel use on oneself - map_freeblock_unlock(); - return 1; - } x = skilllv%11 - 1; i = pc_search_inventory(sd,skill_db[skillid].itemid[x]); if(i < 0 || skill_db[skillid].itemid[x] <= 0) { @@ -3959,7 +3903,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int pc_delitem(sd,i,skill_db[skillid].amount[x],0); sd->state.potionpitcher_flag = 0; if(sd->potion_per_hp > 0 || sd->potion_per_sp > 0) { - hp = battle_get_max_hp(bl) * sd->potion_per_hp / 100; + hp = status_get_max_hp(bl) * sd->potion_per_hp / 100; hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100; if(dstsd) { sp = dstsd->status.max_sp * sd->potion_per_sp / 100; @@ -3969,13 +3913,13 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int else { if(sd->potion_hp > 0) { hp = sd->potion_hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100; - hp = hp * (100 + (battle_get_vit(bl)<<1)) / 100; + hp = hp * (100 + (status_get_vit(bl)<<1)) / 100; if(dstsd) hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; } if(sd->potion_sp > 0) { sp = sd->potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100; - sp = sp * (100 + (battle_get_int(bl)<<1)) / 100; + sp = sp * (100 + (status_get_int(bl)<<1)) / 100; if(dstsd) sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100; } @@ -3983,7 +3927,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int } else { hp = (1 + rand()%400) * (100 + skilllv*10) / 100; - hp = hp * (100 + (battle_get_vit(bl)<<1)) / 100; + hp = hp * (100 + (status_get_vit(bl)<<1)) / 100; if(dstsd) hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; } @@ -4000,39 +3944,16 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int } break; case AM_CP_WEAPON: - { - struct status_change *tsc_data = battle_get_sc_data(bl); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(tsc_data && tsc_data[SC_STRIPWEAPON].timer != -1) - skill_status_change_end(bl, SC_STRIPWEAPON, -1 ); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - } - break; case AM_CP_SHIELD: - { - struct status_change *tsc_data = battle_get_sc_data(bl); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(tsc_data && tsc_data[SC_STRIPSHIELD].timer != -1) - skill_status_change_end(bl, SC_STRIPSHIELD, -1 ); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - } - break; case AM_CP_ARMOR: - { - struct status_change *tsc_data = battle_get_sc_data(bl); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(tsc_data && tsc_data[SC_STRIPARMOR].timer != -1) - skill_status_change_end(bl, SC_STRIPARMOR, -1 ); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - } - break; case AM_CP_HELM: { - struct status_change *tsc_data = battle_get_sc_data(bl); + int scid = SC_STRIPWEAPON + (skillid - AM_CP_WEAPON); + struct status_change *tsc_data = status_get_sc_data(bl); clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(tsc_data && tsc_data[SC_STRIPHELM].timer != -1) - skill_status_change_end(bl, SC_STRIPHELM, -1 ); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + if(tsc_data && tsc_data[scid].timer != -1) + status_change_end(bl, scid, -1 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); } break; @@ -4040,7 +3961,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int { int i; clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + if(dstsd && dstsd->special_state.no_magic_damage ) break; for(i=0;i<136;i++){ if(i==SC_RIDING || i== SC_FALCON || i==SC_HALLUCINATION || i==SC_WEIGHT50 @@ -4048,7 +3969,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int || i==SC_STRIPHELM || i==SC_CP_WEAPON || i==SC_CP_SHIELD || i==SC_CP_ARMOR || i==SC_CP_HELM || i==SC_COMBO) continue; - skill_status_change_end(bl,i,-1); + status_change_end(bl,i,-1); } } break; @@ -4056,12 +3977,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case TF_BACKSLIDING: /* ƒoƒbƒNƒXƒeƒbƒv */ battle_stopwalking(src,1); skill_blown(src,bl,skill_get_blewcount(skillid,skilllv)|0x10000); - if(src->type == BL_MOB) - clif_fixmobpos((struct mob_data *)src); - else if(src->type == BL_PET) - clif_fixpetpos((struct pet_data *)src); - else if(src->type == BL_PC) + if (sd) clif_fixpos(src); + else if (md) + clif_fixmobpos(md); + else if (src->type == BL_PET) + clif_fixpetpos((struct pet_data *)src); skill_addtimerskill(src,tick + 200,src->id,0,0,skillid,skilllv,0,flag); break; @@ -4077,7 +3998,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int break; case SA_SPELLBREAKER: // ƒXƒyƒ‹ƒuƒŒƒCƒJ? { - struct status_change *sc_data = battle_get_sc_data(bl); + struct status_change *sc_data = status_get_sc_data(bl); int sp; if(sc_data && sc_data[SC_MAGICROD].timer != -1) { if(dstsd) { @@ -4140,9 +4061,9 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int } break; case SA_MAGICROD: - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + if (dstsd && dstsd->special_state.no_magic_damage ) break; - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); break; case SA_AUTOSPELL: /* ƒI?ƒgƒXƒyƒ‹ */ clif_skill_nodamage(src,bl,skillid,skilllv,1); @@ -4173,7 +4094,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int maxlv = 3; } if(spellid > 0) - skill_status_change_start(src,SC_AUTOSPELL,skilllv,spellid,maxlv,0, + status_change_start(src,SC_AUTOSPELL,skilllv,spellid,maxlv,0, skill_get_time(SA_AUTOSPELL,skilllv),0); } break; @@ -4201,14 +4122,14 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case NPC_PROVOCATION: clif_skill_nodamage(src,bl,skillid,skilllv,1); if(md) - clif_pet_performance(src,mob_db[md->class].skill[md->skillidx].val[0]); + clif_pet_performance(src,mob_db[md->class_].skill[md->skillidx].val[0]); break; case NPC_HALLUCINATION: clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + if(dstsd && dstsd->special_state.no_magic_damage ) break; - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); break; case NPC_KEEPING: @@ -4216,25 +4137,25 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int { int skill_time = skill_get_time(skillid,skilllv); clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_time,0 ); - if (bl->type == BL_MOB) - mob_changestate((struct mob_data *)src,MS_DELAY,skill_time); - else if (bl->type == BL_PC) + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_time,0 ); + if (md) + mob_changestate(md,MS_DELAY,skill_time); + else if (sd) sd->attackabletime = sd->canmove_tick = tick + skill_time; } break; case NPC_DARKBLESSING: { - int sc_def = 100 - battle_get_mdef(bl); + int sc_def = 100 - status_get_mdef(bl); clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + if(dstsd && dstsd->special_state.no_magic_damage ) break; - if(battle_get_elem_type(bl) == 7 || battle_get_race(bl) == 6) + if(status_get_elem_type(bl) == 7 || status_get_race(bl) == 6) break; if(rand()%100 < sc_def*(50+skilllv*5)/100) { if(dstsd) { - int hp = battle_get_hp(bl)-1; + int hp = status_get_hp(bl)-1; pc_heal(dstsd,-hp,0); } else if(dstmd) @@ -4245,16 +4166,17 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case NPC_SELFDESTRUCTION: /* Ž©”š */ case NPC_SELFDESTRUCTION2: /* Ž©”š2 */ - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,0,0,skill_get_time(skillid,skilllv),0); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,0,0,skill_get_time(skillid,skilllv),0); break; case NPC_LICK: clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_weapon_damage ) - break; - if(dstsd) + if (dstsd) { + if (dstsd->special_state.no_weapon_damage ) + break; pc_heal(dstsd,0,-100); + } if(rand()%100 < (skilllv*5)*sc_def_vit/100) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); break; case NPC_SUICIDE: /* Ž©Œˆ */ @@ -4269,26 +4191,106 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case NPC_SUMMONSLAVE: /* Žè‰º¢Š« */ case NPC_SUMMONMONSTER: /* MOB¢Š« */ - if(md && !md->master_id){ - mob_summonslave(md,mob_db[md->class].skill[md->skillidx].val,skilllv,(skillid==NPC_SUMMONSLAVE)?1:0); + if(md) + mob_summonslave(md,mob_db[md->class_].skill[md->skillidx].val,skilllv,(skillid==NPC_SUMMONSLAVE)?1:0); + break; + + case NPC_RECALL: //Žæ‚芪‚«ŒÄ‚Ñ–ß‚µ + if(md) { + int mobcount; + md->recallcount = 0;//‰Šú‰» + md->recall_flag = 0; + mobcount = mob_countslave(md); + if(mobcount > 0) { + md->recall_flag = 1; //mob.c‚Ì[Žæ‚芪‚«ƒ‚ƒ“ƒXƒ^[‚̈—]‚Å—˜—p + md->recallmob_count = mobcount; + } + } + break; + + case NPC_RUNAWAY: //Œã‘Þ + if(md) { + int check; + int dist = skilllv;//Œã‘Þ‚·‚é‹——£ + check = md->dir; //Ž©•ª‚ª‚ǂ̕ûŒü‚ÉŒü‚¢‚Ă邩ƒ`ƒFƒbƒN + md->attacked_id = 0; + md->target_id = 0; + md->state.targettype = NONE_ATTACKABLE; + md->state.skillstate = MSS_IDLE; + switch (check) { + case 0: //Ž©•ª‚ÌŒü‚¢‚Ä‚é•ûŒü‚Æ‹t‚Ɉړ®‚·‚é + mob_walktoxy(md,md->bl.x,md->bl.y-dist,0);//‚»‚µ‚ÄAˆÚ“®‚·‚é + break; + case 1: + mob_walktoxy(md,md->bl.x-dist,md->bl.y-dist,0); + break; + case 2: + mob_walktoxy(md,md->bl.x+dist,md->bl.y,0); + break; + case 3: + mob_walktoxy(md,md->bl.x+dist,md->bl.y+dist,0); + break; + case 4: + mob_walktoxy(md,md->bl.x,md->bl.y+dist,0); + break; + case 5: + mob_walktoxy(md,md->bl.x-dist,md->bl.y+dist,0); + break; + case 6: + mob_walktoxy(md,md->bl.x-dist,md->bl.y,0); + break; + case 7: + mob_walktoxy(md,md->bl.x-dist,md->bl.y-dist,0); + break; + } } break; case NPC_TRANSFORMATION: case NPC_METAMORPHOSIS: if(md) - mob_class_change(md,mob_db[md->class].skill[md->skillidx].val); + mob_class_change(md,mob_db[md->class_].skill[md->skillidx].val); break; case NPC_EMOTION: /* ƒGƒ‚?ƒVƒ‡ƒ“ */ if(md) - clif_emotion(&md->bl,mob_db[md->class].skill[md->skillidx].val[0]); + clif_emotion(&md->bl,mob_db[md->class_].skill[md->skillidx].val[0]); break; case NPC_DEFENDER: clif_skill_nodamage(src,bl,skillid,skilllv,1); break; + // Equipment breaking monster skills [Celest] + case NPC_BREAKWEAPON: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if(dstsd && battle_config.equipment_breaking) + pc_breakweapon(dstsd); + break; + + case NPC_BREAKARMOR: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if(dstsd && battle_config.equipment_breaking) + pc_breakarmor(dstsd); + break; + + case NPC_BREAKHELM: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if(dstsd && battle_config.equipment_breaking) + pc_breakhelm(dstsd); + break; + + case NPC_BREAKSHIELD: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if(dstsd && battle_config.equipment_breaking) + pc_breakshield(dstsd); + break; + + case NPC_EXPLOSIONSPIRITS: //NPC”š—ô”g“® + clif_skill_nodamage(src,bl,skillid,skilllv,1); + status_change_start(bl,SC_EXPLOSIONSPIRITS,skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + break; + case WE_MALE: /* ŒN‚¾‚¯‚ÍŒì‚邿 */ if(sd && dstsd){ int hp_rate=(skilllv <= 0)? 0:skill_db[skillid].hp_rate[skilllv-1]; @@ -4310,27 +4312,85 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int if(sd && dstsd){ if((dstsd = pc_get_partner(sd)) == NULL){ clif_skill_fail(sd,skillid,0,0); + map_freeblock_unlock(); return 0; } if(map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto || map[dstsd->bl.m].flag.nowarp){ clif_skill_teleportmessage(sd,1); + map_freeblock_unlock(); return 0; - } + } skill_unitsetting(src,skillid,skilllv,sd->bl.x,sd->bl.y,0); } break; +// parent-baby skills + case WE_BABY: + if(sd && dstsd){ + struct map_session_data *f_sd = pc_get_father(sd); + struct map_session_data *m_sd = pc_get_mother(sd); + // if neither was found + if(!f_sd && !m_sd){ + clif_skill_fail(sd,skillid,0,0); + map_freeblock_unlock(); + return 0; + } + status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); + if (f_sd) status_change_start(&f_sd->bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + if (m_sd) status_change_start(&m_sd->bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + } + break; + + case WE_CALLPARENT: + if(sd && dstsd){ + struct map_session_data *f_sd = pc_get_father(sd); + struct map_session_data *m_sd = pc_get_mother(sd); + // if neither was found + if(!f_sd && !m_sd){ + clif_skill_fail(sd,skillid,0,0); + map_freeblock_unlock(); + return 0; + } + if(map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto || map[dstsd->bl.m].flag.nowarp){ + clif_skill_teleportmessage(sd,1); + map_freeblock_unlock(); + return 0; + } + if (f_sd) pc_setpos(f_sd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,3); + if (m_sd) pc_setpos(f_sd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,3); + } + break; + + case WE_CALLBABY: + if(sd && dstsd){ + if((dstsd = pc_get_child(sd)) == NULL){ + clif_skill_fail(sd,skillid,0,0); + map_freeblock_unlock(); + return 0; + } + if(map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto || map[dstsd->bl.m].flag.nowarp){ + clif_skill_teleportmessage(sd,1); + map_freeblock_unlock(); + return 0; + } + pc_setpos(dstsd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,3); + } + break; + case PF_HPCONVERSION: /* ƒ‰ƒCƒt’u‚«Š·‚¦ */ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(sd){ - int conv_hp=0,conv_sp=0; - conv_hp=sd->status.hp/10; //Šî–{‚ÍHP‚Ì10% - sd->status.hp -= conv_hp; //HP‚ðŒ¸‚ç‚· - conv_sp=conv_hp*10*skilllv/100; - conv_sp=(sd->status.sp+conv_sp>sd->status.max_sp)?sd->status.max_sp-sd->status.sp:conv_sp; - sd->status.sp += conv_sp; //SP‚ð?‚â‚· - pc_heal(sd,-conv_hp,conv_sp); - clif_heal(sd->fd,SP_SP,conv_sp); + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + if (sd) { + int hp, sp; + hp = sd->status.max_hp / 10; //Šî–{‚ÍHP‚Ì10% + sp = hp * 10 * skilllv / 100; + if (sd->status.sp + sp > sd->status.max_sp) + sp = sd->status.max_sp - sd->status.sp; + // we need to check with the sp that was taken away when casting too + if (sd->status.sp + skill_get_sp(skillid, skilllv) >= sd->status.max_sp) + hp = sp = 0; + pc_heal(sd, -hp, sp); + clif_heal(sd->fd, SP_SP, sp); + clif_updatestatus(sd, SP_SP); } break; case HT_REMOVETRAP: /* ƒŠƒ€?ƒuƒgƒ‰ƒbƒv */ @@ -4346,13 +4406,13 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int (su->group->unit_id != 0x92)){ //?‚ðŽæ‚è•Ô‚· if(sd){ if(battle_config.skill_removetrap_type == 1){ - for(i=0;i<10;i++) { - if(skill_db[su->group->skill_id].itemid[i] > 0){ - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = skill_db[su->group->skill_id].itemid[i]; - item_tmp.identify = 1; - if(item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,skill_db[su->group->skill_id].amount[i]))){ - clif_additem(sd,0,0,flag); + for(i=0;i<10;i++) { + if(skill_db[su->group->skill_id].itemid[i] > 0){ + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid = skill_db[su->group->skill_id].itemid[i]; + item_tmp.identify = 1; + if(item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,skill_db[su->group->skill_id].amount[i]))){ + clif_additem(sd,0,0,flag); map_addflooritem(&item_tmp,skill_db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); } } @@ -4366,12 +4426,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); } } - + } if(su->group->unit_id == 0x91 && su->group->val2){ struct block_list *target=map_id2bl(su->group->val2); if(target && (target->type == BL_PC || target->type == BL_MOB)) - skill_status_change_end(target,SC_ANKLE,-1); + status_change_end(target,SC_ANKLE,-1); } skill_delunit(su); } @@ -4383,6 +4443,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int struct skill_unit *su=NULL; if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){ switch(su->group->unit_id){ + case 0x91: // ankle snare + if (su->group->val2 != 0) + // if it is already trapping something don't spring it, + // remove trap should be used instead + break; + // otherwise fallthrough to below case 0x8f: /* ƒuƒ‰ƒXƒgƒ}ƒCƒ“ */ case 0x90: /* ƒXƒLƒbƒhƒgƒ‰ƒbƒv */ case 0x93: /* ƒ‰ƒ“ƒhƒ}ƒCƒ“ */ @@ -4407,25 +4473,27 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int break; case AS_SPLASHER: /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ? */ - if((double)battle_get_max_hp(bl)*2/3 < battle_get_hp(bl)) //HP‚ª2/3ˆÈã?‚Á‚Ä‚¢‚½‚玸”s + if((double)status_get_max_hp(bl)*2/3 < status_get_hp(bl)) { //HP‚ª2/3ˆÈã?‚Á‚Ä‚¢‚½‚玸”s + map_freeblock_unlock(); return 1; + } clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,src->id,0,skill_get_time(skillid,skilllv),0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,src->id,skill_get_time(skillid,skilllv),1000,0 ); break; case PF_MINDBREAKER: /* ƒvƒƒ{ƒbƒN */ { - struct status_change *sc_data = battle_get_sc_data(bl); + struct status_change *sc_data = status_get_sc_data(bl); /* MVPmob‚Æ•sŽ€‚É‚Í?‚©‚È‚¢ */ - if((bl->type==BL_MOB && battle_get_mode(bl)&0x20) || battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) //•sŽ€‚É‚Í?‚©‚È‚¢ + if((dstmd && status_get_mode(bl)&0x20) || battle_check_undead(status_get_race(bl),status_get_elem_type(bl))) //•sŽ€‚É‚Í?‚©‚È‚¢ { map_freeblock_unlock(); return 1; } clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); + status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); if(dstmd && dstmd->skilltimer!=-1 && dstmd->state.skillcastcancel) // ‰r¥–WŠQ skill_castcancel(bl,0); @@ -4435,22 +4503,55 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int if(sc_data){ if(sc_data[SC_FREEZE].timer!=-1) - skill_status_change_end(bl,SC_FREEZE,-1); + status_change_end(bl,SC_FREEZE,-1); if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0) - skill_status_change_end(bl,SC_STONE,-1); + status_change_end(bl,SC_STONE,-1); if(sc_data[SC_SLEEP].timer!=-1) - skill_status_change_end(bl,SC_SLEEP,-1); + status_change_end(bl,SC_SLEEP,-1); } - if(bl->type==BL_MOB) { - int range = skill_get_range(skillid,skilllv); - if(range < 0) - range = battle_get_range(src) - (range + 1); - mob_target((struct mob_data *)bl,src,range); + if(dstmd) + mob_target(dstmd,src,skill_get_range(skillid,skilllv)); + } + break; + + case PF_SOULCHANGE: + { + int sp1 = 0, sp2 = 0; + if (sd) { + if (dstsd) { + sp1 = sd->status.sp > dstsd->status.max_sp ? dstsd->status.max_sp : sd->status.sp; + sp2 = dstsd->status.sp > sd->status.max_sp ? sd->status.max_sp : dstsd->status.sp; + sd->status.sp = sp2; + dstsd->status.sp = sp1; + clif_heal(sd->fd,SP_SP,sp2); + clif_updatestatus(sd,SP_SP); + clif_heal(dstsd->fd,SP_SP,sp1); + clif_updatestatus(dstsd,SP_SP); + } else if (dstmd) { + if (dstmd->state.soul_change_flag) { + clif_skill_fail(sd,skillid,0,0); + map_freeblock_unlock(); + return 0; + } + sp2 = sd->status.max_sp * 3 /100; + if (sd->status.sp + sp2 > sd->status.max_sp) + sp2 = sd->status.max_sp - sd->status.sp; + sd->status.sp += sp2; + clif_heal(sd->fd,SP_SP,sp2); + clif_updatestatus(sd,SP_SP); + dstmd->state.soul_change_flag = 1; + } } + clif_skill_nodamage(src,bl,skillid,skilllv,1); } break; + case PF_SPIDERWEB: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ + clif_skill_nodamage(src,bl,skillid,skilllv,1); + skill_unitsetting(src,skillid,skilllv,bl->x,bl->y,0); + break; + // Weapon Refining [Celest] case WS_WEAPONREFINE: if(sd) @@ -4461,12 +4562,18 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case CR_SLIMPITCHER: { if (sd && flag&1) { - int hp = sd->potion_hp * (100 + pc_checkskill(sd,CR_SLIMPITCHER)*5 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100; - hp = hp * (100 + (battle_get_vit(bl)<<1))/100; - if (dstsd) + struct block_list tbl; + int hp = sd->potion_hp * (100 + pc_checkskill(sd,CR_SLIMPITCHER)*10 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100; + hp = hp * (100 + (status_get_vit(bl)<<1))/100; + if (dstsd) { hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10)/100; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - battle_heal(src,bl,hp,0,0); + } + tbl.id = 0; + tbl.m = src->m; + tbl.x = src->x; + tbl.y = src->y; + clif_skill_nodamage(&tbl,bl,AL_HEAL,hp,1); + battle_heal(NULL,bl,hp,0,0); } } break; @@ -4474,13 +4581,13 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int case CR_FULLPROTECTION: { int i, skilltime; - struct status_change *tsc_data = battle_get_sc_data(bl); + struct status_change *tsc_data = status_get_sc_data(bl); clif_skill_nodamage(src,bl,skillid,skilllv,1); skilltime = skill_get_time(skillid,skilllv); for (i=0; i<4; i++) { if(tsc_data && tsc_data[SC_STRIPWEAPON + i].timer != -1) - skill_status_change_end(bl, SC_STRIPWEAPON + i, -1 ); - skill_status_change_start(bl,SC_CP_WEAPON + i,skilllv,0,0,0,skilltime,0 ); + status_change_end(bl, SC_STRIPWEAPON + i, -1 ); + status_change_start(bl,SC_CP_WEAPON + i,skilllv,0,0,0,skilltime,0 ); } } break; @@ -4498,6 +4605,15 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int } } break; + case ST_PRESERVE: + if (sd){ + if (sd->sc_count && sd->sc_data[SC_PRESERVE].timer != -1) + status_change_end(src, SC_PRESERVE, -1 ); + else + status_change_start(src,SC_PRESERVE,skilllv,0,0,0,skill_get_time(skillid, skilllv),0 ); + clif_skill_nodamage(src,src,skillid,skilllv,1); + } + break; // New guild skills [Celest] case GD_BATTLEORDER: @@ -4511,7 +4627,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int } if(flag&1) { if (dstsd && dstsd->status.guild_id == sd->status.guild_id) { - skill_status_change_start(&dstsd->bl,SC_BATTLEORDERS,skilllv,0,0,0,0,0 ); + status_change_start(&dstsd->bl,SC_BATTLEORDERS,skilllv,0,0,0,0,0 ); } } else if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) && @@ -4521,6 +4637,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int src->m,src->x-15,src->y-15,src->x+15,src->y+15,0, src,skillid,skilllv,tick, flag|BCT_ALL|1, skill_castend_nodamage_id); + pc_blockskill_start (sd, skillid, 300000); } } break; @@ -4535,7 +4652,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int } if(flag&1) { if (dstsd && dstsd->status.guild_id == sd->status.guild_id) { - skill_status_change_start(&dstsd->bl,SC_REGENERATION,skilllv,0,0,0,0,0 ); + status_change_start(&dstsd->bl,SC_REGENERATION,skilllv,0,0,0,0,0 ); } } else if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) && @@ -4545,10 +4662,11 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int src->m,src->x-15,src->y-15,src->x+15,src->y+15,0, src,skillid,skilllv,tick, flag|BCT_ALL|1, skill_castend_nodamage_id); + pc_blockskill_start (sd, skillid, 300000); } } break; - case GD_RESTORE: + case GD_RESTORE: { struct guild *g = NULL; // Only usable during WoE @@ -4560,8 +4678,8 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int if(flag&1) { if (dstsd && dstsd->status.guild_id == sd->status.guild_id) { int hp, sp; - hp = dstsd->status.max_hp*0.9; - sp = dstsd->status.max_sp*0.9; + hp = dstsd->status.max_hp*9/10; + sp = dstsd->status.max_sp*9/10; sp = dstsd->status.sp + sp <= dstsd->status.max_sp ? sp : dstsd->status.max_sp - dstsd->status.sp; clif_skill_nodamage(src,bl,AL_HEAL,hp,1); battle_heal(NULL,bl,hp,sp,0); @@ -4574,6 +4692,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int src->m,src->x-15,src->y-15,src->x+15,src->y+15,0, src,skillid,skilllv,tick, flag|BCT_ALL|1, skill_castend_nodamage_id); + pc_blockskill_start (sd, skillid, 300000); } } break; @@ -4581,10 +4700,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int { int dx[9]={-1, 1, 0, 0,-1, 1,-1, 1, 0}; int dy[9]={ 0, 0, 1,-1, 1,-1,-1, 1, 0}; - int c, j = 0; + int j = 0; struct guild *g = NULL; // Only usable during WoE - if (!agit_flag) { + if (!agit_flag || + (sd && map[sd->bl.m].flag.nowarpto && // if not allowed to warp to the map + guild_mapname2gc(sd->mapname) == NULL)) { // and it's not a castle... clif_skill_fail(sd,skillid,0,0); map_freeblock_unlock(); return 0; @@ -4594,17 +4715,21 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int strcmp(sd->status.name,g->master)==0) { for(i = 0; i < g->max_member; i++, j++) { if (j>8) j=0; - if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && - !map[sd->bl.m].flag.nowarpto && !map[dstsd->bl.m].flag.nowarp) { + if ((dstsd = g->member[i].sd) != NULL && sd != dstsd) { + if (map[dstsd->bl.m].flag.nowarp && + guild_mapname2gc(sd->mapname) == NULL) + continue; clif_skill_nodamage(src,bl,skillid,skilllv,1); - if ((c=read_gat(sd->bl.m,sd->bl.x+dx[j],sd->bl.y+dy[j]))==1 || c==5) + if(map_getcell(sd->bl.m,sd->bl.x+dx[j],sd->bl.y+dy[j],CELL_CHKNOPASS)) dx[j] = dy[j] = 0; pc_setpos(dstsd, sd->mapname, sd->bl.x+dx[j], sd->bl.y+dy[j], 2); } } + pc_blockskill_start (sd, skillid, 300000); } } break; + default: printf("Unknown skill used:%d\n",skillid); map_freeblock_unlock(); @@ -4653,7 +4778,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data ) } if(sd->skillid == PR_LEXAETERNA) { - struct status_change *sc_data = battle_get_sc_data(bl); + struct status_change *sc_data = status_get_sc_data(bl); if(sc_data && (sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0))) { clif_skill_fail(sd,sd->skillid,0,0); sd->canact_tick = tick; @@ -4663,7 +4788,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data ) } } else if(sd->skillid == RG_BACKSTAP) { - int dir = map_calc_dir(&sd->bl,bl->x,bl->y),t_dir = battle_get_dir(bl); + int dir = map_calc_dir(&sd->bl,bl->x,bl->y),t_dir = status_get_dir(bl); int dist = distance(sd->bl.x,sd->bl.y,bl->x,bl->y); if(bl->type != BL_SKILL && (dist == 0 || map_check_dir(dir,t_dir))) { clif_skill_fail(sd,sd->skillid,0,0); @@ -4686,7 +4811,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data ) int fail_flag = 1; if(inf2 & 0x400 && battle_check_target(&sd->bl,bl, BCT_PARTY) > 0) fail_flag = 0; - if(inf2 & 0x800 && sd->status.guild_id > 0 && sd->status.guild_id == battle_get_guild_id(bl)) + if(inf2 & 0x800 && sd->status.guild_id > 0 && sd->status.guild_id == status_get_guild_id(bl)) fail_flag = 0; if(fail_flag) { clif_skill_fail(sd,sd->skillid,0,0); @@ -4699,7 +4824,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data ) range = skill_get_range(sd->skillid,sd->skilllv); if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); + range = status_get_range(&sd->bl) - (range + 1); range += battle_config.pc_skill_add_range; if((sd->skillid == MO_EXTREMITYFIST && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) || (sd->skillid == CH_TIGERFIST && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) || @@ -4742,7 +4867,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data ) skill_castend_damage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0); break; case 1:/* Žx‰‡Œn */ - if( (sd->skillid==AL_HEAL || (sd->skillid==ALL_RESURRECTION && bl->type != BL_PC) || sd->skillid==PR_ASPERSIO) && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) + if( (sd->skillid==AL_HEAL || (sd->skillid==ALL_RESURRECTION && bl->type != BL_PC) || sd->skillid==PR_ASPERSIO) && battle_check_undead(status_get_race(bl),status_get_elem_type(bl))) skill_castend_damage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0); else skill_castend_nodamage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0); @@ -4761,21 +4886,21 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil struct map_session_data *sd=NULL; int i,tmpx = 0,tmpy = 0, x1 = 0, y1 = 0; - if(skilllv <= 0) return 0; + //if(skilllv <= 0) return 0; + if(skillid > 0 && skilllv <= 0) return 0; // celest nullpo_retr(0, src); if(src->type==BL_PC){ nullpo_retr(0, sd=(struct map_session_data *)src); } - if( skillid != WZ_METEOR && - skillid != WZ_SIGHTRASHER && + if( skillid != WZ_METEOR && skillid != AM_CANNIBALIZE && skillid != AM_SPHEREMINE) clif_skill_poseffect(src,skillid,skilllv,x,y,tick); - if (skillnotok(skillid, sd)) // [MouseJstr] - return 0; + if (sd && skillnotok(skillid, sd)) // [MouseJstr] + return 0; switch(skillid) { @@ -4792,20 +4917,31 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil break; case BS_HAMMERFALL: /* ƒnƒ“ƒ}?ƒtƒH?ƒ‹ */ - skill_area_temp[1]=src->id; - skill_area_temp[2]=x; - skill_area_temp[3]=y; - map_foreachinarea(skill_area_sub, - src->m,x-2,y-2,x+2,y+2,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY|2, - skill_castend_nodamage_id); + { + int r = 2; + if (skilllv > 5) { + r = 14; + skilllv = 5; // ƒXƒ^ƒ“—¦ã‚ª‚è‚·‚¬‚邽‚ߌvŽZ‚ÍLv5‚ŌŒè + } + skill_area_temp[1] = src->id; + skill_area_temp[2] = x; + skill_area_temp[3] = y; + map_foreachinarea (skill_area_sub, + src->m, x-r, y-r, x+r, y+r, 0, + src, skillid, skilllv, tick, flag|BCT_ENEMY|2, + skill_castend_nodamage_id); + } break; case HT_DETECTING: /* ƒfƒBƒeƒNƒeƒBƒ“ƒO */ { - const int range=7; - map_foreachinarea( skill_status_change_timer_sub, - src->m, src->x-range, src->y-range, src->x+range,src->y+range,0, + int range=skilllv*2+1; + if(src->x!=x) + x+=(src->x-x>0)?-range:range; + if(src->y!=y) + y+=(src->y-y>0)?-range:range; + map_foreachinarea( status_change_timer_sub, + src->m, x-range, y-range, x+range,y+range,0, src,SC_SIGHT,tick); } break; @@ -4816,15 +4952,15 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil case AL_PNEUMA: /* ƒjƒ…?ƒ} */ case WZ_ICEWALL: /* ƒAƒCƒXƒEƒH?ƒ‹ */ case WZ_FIREPILLAR: /* ƒtƒ@ƒCƒAƒsƒ‰? */ - case WZ_SIGHTRASHER: case WZ_QUAGMIRE: /* ƒNƒ@ƒOƒ}ƒCƒA */ case WZ_VERMILION: /* ƒ?ƒhƒIƒuƒ”ƒ@?ƒ~ƒŠƒIƒ“ */ - case WZ_FROSTNOVA: /* ƒtƒƒXƒgƒmƒ”ƒ@ */ + //case WZ_FROSTNOVA: /* ƒtƒƒXƒgƒmƒ”ƒ@ */ case WZ_STORMGUST: /* ƒXƒg?ƒ€ƒKƒXƒg */ case WZ_HEAVENDRIVE: /* ƒwƒ”ƒ“ƒYƒhƒ‰ƒCƒu */ case PR_SANCTUARY: /* ƒTƒ“ƒNƒ`ƒ…ƒAƒŠ */ case PR_MAGNUS: /* ƒ}ƒOƒkƒXƒGƒNƒ\ƒVƒYƒ€ */ case CR_GRANDCROSS: /* ƒOƒ‰ƒ“ƒhƒNƒƒX */ + case NPC_DARKGRANDCROSS: /*ˆÅƒOƒ‰ƒ“ƒhƒNƒƒX*/ case HT_SKIDTRAP: /* ƒXƒLƒbƒhƒgƒ‰ƒbƒv */ case HT_LANDMINE: /* ƒ‰ƒ“ƒhƒ}ƒCƒ“ */ case HT_ANKLESNARE: /* ƒAƒ“ƒNƒ‹ƒXƒlƒA */ @@ -4836,12 +4972,11 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil case HT_CLAYMORETRAP: /* ƒNƒŒƒCƒ‚ƒA?ƒgƒ‰ƒbƒv */ case AS_VENOMDUST: /* ƒxƒmƒ€ƒ_ƒXƒg */ case AM_DEMONSTRATION: /* ƒfƒ‚ƒ“ƒXƒgƒŒ?ƒVƒ‡ƒ“ */ - case PF_SPIDERWEB: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ case PF_FOGWALL: /* ƒtƒHƒOƒEƒH?ƒ‹ */ case HT_TALKIEBOX: /* ƒg?ƒL?ƒ{ƒbƒNƒX */ skill_unitsetting(src,skillid,skilllv,x,y,0); break; - + case RG_GRAFFITI: /* Graffiti [Valaris] */ skill_clear_unitgroup(src); skill_unitsetting(src,skillid,skilllv,x,y,0); @@ -4859,7 +4994,7 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil { int flag=0; for(i=0;i<2+(skilllv>>1);i++) { - int j=0, c; + int j=0; do { tmpx = x + (rand()%7 - 3); tmpy = y + (rand()%7 - 3); @@ -4872,7 +5007,7 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil else if(tmpy >= map[src->m].ys) tmpy = map[src->m].ys - 1; j++; - } while(((c=map_getcell(src->m,tmpx,tmpy))==1 || c==5) && j<100); + } while((map_getcell(src->m,tmpx,tmpy,CELL_CHKNOPASS)) && j<100); if(j >= 100) continue; if(flag==0){ @@ -4903,37 +5038,43 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil pc_movepos(sd,x,y); }else if( src->type==BL_MOB ) mob_warp((struct mob_data *)src,-1,x,y,0); + if (sd) + pc_blockskill_start (sd, MO_EXTREMITYFIST, 2000); break; case AM_CANNIBALIZE: // ƒoƒCƒIƒvƒ‰ƒ“ƒg - if(sd){ - int mx,my,id=0; + if(sd) { + int id; + int summons[5] = { 1020, 1068, 1118, 1500, 1368 }; struct mob_data *md; - mx = x;// + (rand()%10 - 5); - my = y;// + (rand()%10 - 5); - id=mob_once_spawn(sd,"this",mx,my,"--ja--",1118,1,""); + // Correct info, don't change any of this! [celest] + id = mob_once_spawn (sd, "this", x, y, "--ja--", summons[skilllv-1] ,1,""); + if( (md=(struct mob_data *)map_id2bl(id)) !=NULL ){ - md->master_id=sd->bl.id; - md->hp=2210+skilllv*200; - md->state.special_mob_ai=1; - md->deletetimer=add_timer(gettick()+skill_get_time(skillid,skilllv),mob_timer_delete,id,0); - } + md->master_id = sd->bl.id; + // different levels of HP according to skill level + md->hp = 1500 + skilllv * 200 + sd->status.base_level * 10; + md->state.special_mob_ai = 1; + //”ñˆÚ“®‚ŃAƒNƒeƒBƒu‚Å”½Œ‚‚·‚é[0x0:”ñˆÚ“® 0x1:ˆÚ“® 0x4:ACT 0x8:”ñACT 0x40:”½Œ‚–³ 0x80:”½Œ‚—L] + md->mode = 0x0 + 0x4 + 0x80; + md->deletetimer = add_timer (gettick() + skill_get_time(skillid,skilllv), mob_timer_delete, id, 0); + } + // To-do: ¢ŠÒ‚³‚ê‚郂ƒ“ƒXƒ^[‚ɂ͢ŠÒ‚µ‚½ƒvƒŒ[ƒ„[‚Ì–¼‘O‚ª•t‚«‚Ü‚· + // (attach name of player?) clif_skill_poseffect(src,skillid,skilllv,x,y,tick); } break; case AM_SPHEREMINE: // ƒXƒtƒBƒA?ƒ}ƒCƒ“ if(sd){ - int mx,my,id=0; + int id; struct mob_data *md; - mx = x;// + (rand()%10 - 5); - my = y;// + (rand()%10 - 5); - id=mob_once_spawn(sd,"this",mx,my,"--ja--",1142,1,""); + id = mob_once_spawn(sd, "this", x, y, "--ja--", 1142, 1, ""); if( (md=(struct mob_data *)map_id2bl(id)) !=NULL ){ - md->master_id=sd->bl.id; - md->hp=1000+skilllv*200; - md->state.special_mob_ai=2; - md->deletetimer=add_timer(gettick()+skill_get_time(skillid,skilllv),mob_timer_delete,id,0); + md->master_id = sd->bl.id; + md->hp = 2000 + skilllv * 400; + md->state.special_mob_ai = 2; + md->deletetimer = add_timer (gettick() + skill_get_time(skillid,skilllv), mob_timer_delete, id, 0); } clif_skill_poseffect(src,skillid,skilllv,x,y,tick); } @@ -4943,24 +5084,24 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil case CR_SLIMPITCHER: { if (sd) { - int x = skilllv%11 - 1; - int i = pc_search_inventory(sd,skill_db[skillid].itemid[x]); - if(i < 0 || skill_db[skillid].itemid[x] <= 0 || sd->inventory_data[i] == NULL || - sd->status.inventory[i].amount < skill_db[skillid].amount[x]) { + int i = skilllv%11 - 1; + int j = pc_search_inventory(sd,skill_db[skillid].itemid[i]); + if(j < 0 || skill_db[skillid].itemid[i] <= 0 || sd->inventory_data[j] == NULL || + sd->status.inventory[j].amount < skill_db[skillid].amount[i]) { clif_skill_fail(sd,skillid,0,0); - map_freeblock_unlock(); return 1; } sd->state.potionpitcher_flag = 1; sd->potion_hp = 0; - run_script(sd->inventory_data[i]->use_script,0,sd->bl.id,0); - pc_delitem(sd,i,skill_db[skillid].amount[x],0); + run_script(sd->inventory_data[j]->use_script,0,sd->bl.id,0); + pc_delitem(sd,j,skill_db[skillid].amount[i],0); sd->state.potionpitcher_flag = 0; + clif_skill_poseffect(src,skillid,skilllv,x,y,tick); if(sd->potion_hp > 0) { map_foreachinarea(skill_area_sub, src->m,x-3,y-3,x+3,y+3,0, - src,skillid,skilllv,tick,flag|BCT_ALL|1, - skill_castend_nodamage_id); + src,skillid,skilllv,tick,flag|BCT_PARTY|1, + skill_castend_nodamage_id); } } } @@ -4982,13 +5123,13 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma if( sd->bl.prev == NULL || pc_isdead(sd) ) return 0; - if(skillnotok(skill_num, sd)) - return 0; + if(skillnotok(skill_num, sd)) + return 0; if( sd->opt1>0 || sd->status.option&2 ) return 0; //ƒXƒLƒ‹‚ªŽg‚¦‚È‚¢?‘ÔˆÙí’† - if(sd->sc_data){ + if(sd->sc_count){ if( sd->sc_data[SC_DIVINA].timer!=-1 || sd->sc_data[SC_ROKISWEIL].timer!=-1 || sd->sc_data[SC_AUTOCOUNTER].timer != -1 || @@ -4997,10 +5138,6 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma sd->sc_data[SC_BERSERK].timer != -1 || sd->sc_data[SC_MARIONETTE].timer != -1) return 0; - - if (sd->sc_data[SC_BLOCKSKILL].timer!=-1) - if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3) - return 0; } if( skill_num != sd->skillid) /* •s³ƒpƒPƒbƒg‚炵‚¢ */ @@ -5026,13 +5163,14 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma case AL_WARP: /* ƒ?ƒvƒ|?ƒ^ƒ‹ */ { - const struct point *p[]={ - &sd->status.save_point,&sd->status.memo_point[0], - &sd->status.memo_point[1],&sd->status.memo_point[2], - }; + const struct point *p[4]; struct skill_unit_group *group; int i; int maxcount=0; + p[0] = &sd->status.save_point; + p[1] = &sd->status.memo_point[0]; + p[2] = &sd->status.memo_point[1]; + p[3] = &sd->status.memo_point[2]; if((maxcount = skill_get_maxcount(sd->skillid)) > 0) { int c; @@ -5064,7 +5202,7 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma return 0; if((group=skill_unitsetting(&sd->bl,sd->skillid,sd->skilllv,sd->skillx,sd->skilly,0))==NULL) return 0; - group->valstr=(char *)aCalloc(24,sizeof(char)); + group->valstr=(char *)aCallocA(24,sizeof(char)); memcpy(group->valstr,map,24); group->val2=(x<<16)|y; } @@ -5081,561 +5219,176 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag) { struct skill_unit_group *group; - int i,count=1,limit=10000,val1=0,val2=0; - int target=BCT_ENEMY,interval=1000,range=0; - int dir=0,aoe_diameter=0; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills - struct status_change *sc_data = battle_get_sc_data(src); // for firewall and fogwall - celest + int i,limit,val1=0,val2=0,val3=0; + int count=0; + int target,interval,range,unit_flag; + struct skill_unit_layout *layout; + struct status_change *sc_data; + int active_flag=1; nullpo_retr(0, src); + limit = skill_get_time(skillid,skilllv); + range = skill_get_unit_range(skillid); + interval = skill_get_unit_interval(skillid); + target = skill_get_unit_target(skillid); + unit_flag = skill_get_unit_flag(skillid); + layout = skill_get_unit_layout(skillid,skilllv,src,x,y); + + if (unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy) + target = BCT_NOENEMY; + + sc_data = status_get_sc_data(src); // for firewall and fogwall - celest + switch(skillid){ /* Ý’è */ case MG_SAFETYWALL: /* ƒZƒCƒtƒeƒBƒEƒH?ƒ‹ */ - limit=skill_get_time(skillid,skilllv); val2=skilllv+1; - interval = -1; - target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL; break; - case MG_FIREWALL: /* ƒtƒ@ƒCƒ„?ƒEƒH?ƒ‹ */ - if(src->x == x && src->y == y) - dir = 2; - else - dir=map_calc_dir(src,x,y); - if(dir&1) count=5; - else count=3; - limit=skill_get_time(skillid,skilllv); - if(sc_data) { - if (sc_data[SC_VIOLENTGALE].timer!=-1) limit *= 1.5; - } - // check for sc_data first - Celest - // if (((struct map_session_data *)src)->sc_data[SC_VIOLENTGALE].timer!=-1) - // limit *= 1.5; + if(sc_data && sc_data[SC_VIOLENTGALE].timer!=-1) + limit = limit*3/2; val2=4+skilllv; - interval=1; - break; - - case AL_PNEUMA: /* ƒjƒ…?ƒ} */ - limit=skill_get_time(skillid,skilllv); - interval = -1; - target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL; - count = 9; break; case AL_WARP: /* ƒ?ƒvƒ|?ƒ^ƒ‹ */ - target=BCT_ALL; val1=skilllv+6; if(flag==0) limit=2000; - else - limit=skill_get_time(skillid,skilllv); + active_flag=0; break; case PR_SANCTUARY: /* ƒTƒ“ƒNƒ`ƒ…ƒAƒŠ */ - count=21; - limit=skill_get_time(skillid,skilllv); - val1=skilllv+3; + val1=(skilllv+3)*2; val2=(skilllv>6)?777:skilllv*100; - target=BCT_ALL; - range=1; - break; - - case PR_MAGNUS: /* ƒ}ƒOƒkƒXƒGƒNƒ\ƒVƒYƒ€ */ - count=33; - limit=skill_get_time(skillid,skilllv); - interval=3000; + interval += 500; break; case WZ_FIREPILLAR: /* ƒtƒ@ƒCƒA?ƒsƒ‰? */ - if(flag==0) - limit=skill_get_time(skillid,skilllv); - else + if(flag!=0) limit=1000; - interval=2000; val1=skilllv+2; - if(skilllv < 6) - range=1; - else - range=2; - break; - - case MG_THUNDERSTORM: /* ƒTƒ“ƒ_?ƒXƒg?ƒ€ */ - limit=500; - range=1; - break; - - case WZ_FROSTNOVA: /* ƒtƒƒXƒgƒmƒ”ƒ@ */ - limit=500; - range=5; - break; - - case WZ_HEAVENDRIVE: /* ƒwƒ”ƒ“ƒYƒhƒ‰ƒCƒu */ - limit=500; - range=2; - break; - - case WZ_METEOR: /* ƒƒeƒIƒXƒg?ƒ€ */ - limit=500; - range=3; - break; - - case WZ_SIGHTRASHER: - limit=500; - count=41; - break; - - case WZ_VERMILION: /* ƒ?ƒhƒIƒuƒ”ƒ@?ƒ~ƒŠƒIƒ“ */ - limit=4100; - interval=1000; - range=6; - break; - - case WZ_ICEWALL: /* ƒAƒCƒXƒEƒH?ƒ‹ */ - limit=skill_get_time(skillid,skilllv); - count=5; + if(skilllv >= 6) + range=2; break; - - case WZ_STORMGUST: /* ƒXƒg?ƒ€ƒKƒXƒg */ - limit=4600; - interval=450; - range=5; + case WZ_METEOR: + if (skilllv > 10) //L”͈̓ƒeƒI + range = 10; break; - - case WZ_QUAGMIRE: /* ƒNƒ@ƒOƒ}ƒCƒA */ - limit=skill_get_time(skillid,skilllv); - interval=200; - count=25; + case WZ_VERMILION: + if (skilllv > 10) //L”͈ÍLOV + range = 25; break; case HT_SANDMAN: /* ƒTƒ“ƒhƒ}ƒ“ */ case HT_CLAYMORETRAP: /* ƒNƒŒƒCƒ‚ƒA?ƒgƒ‰ƒbƒv */ - limit=skill_get_time(skillid,skilllv); - range=2; - break; case HT_SKIDTRAP: /* ƒXƒLƒbƒhƒgƒ‰ƒbƒv */ case HT_LANDMINE: /* ƒ‰ƒ“ƒhƒ}ƒCƒ“ */ case HT_ANKLESNARE: /* ƒAƒ“ƒNƒ‹ƒXƒlƒA */ - case PF_SPIDERWEB: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ case HT_FLASHER: /* ƒtƒ‰ƒbƒVƒƒ? */ case HT_FREEZINGTRAP: /* ƒtƒŠ?ƒWƒ“ƒOƒgƒ‰ƒbƒv */ case HT_BLASTMINE: /* ƒuƒ‰ƒXƒgƒ}ƒCƒ“ */ - limit=skill_get_time(skillid,skilllv); - range=1; + // longer trap times in WOE [celest] + if (map[src->m].flag.gvg) limit *= 4; break; - - case HT_TALKIEBOX: /* ƒg?ƒL?ƒ{ƒbƒNƒX */ - limit=skill_get_time(skillid,skilllv); - range=1; - target=BCT_ALL; - break; - case HT_SHOCKWAVE: /* ƒVƒ‡ƒbƒNƒEƒF?ƒuƒgƒ‰ƒbƒv */ - limit=skill_get_time(skillid,skilllv); - range=1; val1=skilllv*15+10; break; - case AS_VENOMDUST: /* ƒxƒmƒ€ƒ_ƒXƒg */ - limit=skill_get_time(skillid,skilllv); - interval=1000; - count=5; - break; - - case CR_GRANDCROSS: /* ƒOƒ‰ƒ“ƒhƒNƒƒX */ - count=29; - limit=1000; - interval=300; - break; - - case SA_VOLCANO: /* ƒ{ƒ‹ƒP?ƒm */ - case SA_DELUGE: /* ƒfƒŠƒ…?ƒW */ - case SA_VIOLENTGALE: /* ƒoƒCƒIƒŒƒ“ƒgƒQƒCƒ‹ */ - limit=skill_get_time(skillid,skilllv); - count=skilllv<=2?25:(skilllv<=4?49:81); - target=BCT_ALL; - break; - case SA_LANDPROTECTOR: /* ƒOƒ‰ƒ“ƒhƒNƒƒX */ - limit=skill_get_time(skillid,skilllv); // changed to get duration from cast_db (moonsoul) - val1=skilllv*15+10; - aoe_diameter=skilllv+skilllv%2+5; - target=BCT_ALL; - count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul) - break; - - case BD_LULLABY: /* ŽqŽç‰S */ - case BD_ETERNALCHAOS: /* ƒGƒ^?ƒiƒ‹ƒJƒIƒX */ - case BD_ROKISWEIL: /* ƒƒL‚Ì‹©‚Ñ */ - count=81; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_ALL; - break; - case BD_RICHMANKIM: - case BD_DRUMBATTLEFIELD: /* ?‘¾ŒÛ‚Ì‹¿‚« */ - case BD_RINGNIBELUNGEN: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ - case BD_INTOABYSS: /* [•£‚Ì’†‚É */ - case BD_SIEGFRIED: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ - count=81; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_PARTY; + { + int aoe_diameter; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills + val1=skilllv*15+10; + aoe_diameter=skilllv+skilllv%2+5; + count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul) + } break; case BA_WHISTLE: /* Œû“J */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1; - val2 = ((battle_get_agi(src)/10)&0xffff)<<16; - val2 |= (battle_get_luk(src)/10)&0xffff; + val2 = ((status_get_agi(src)/10)&0xffff)<<16; + val2 |= (status_get_luk(src)/10)&0xffff; break; case DC_HUMMING: /* ƒnƒ~ƒ“ƒO */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; - val2 = battle_get_dex(src)/10; - break; - - case BA_DISSONANCE: /* •s‹¦˜a‰¹ */ - case DC_UGLYDANCE: /* Ž©•ªŸŽè‚ȃ_ƒ“ƒX */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_ENEMY; + val2 = status_get_dex(src)/10; break; - case DC_DONTFORGETME: /* Ž„‚ð–Y‚ê‚È‚¢‚Åc */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_ENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; - val2 = ((battle_get_str(src)/20)&0xffff)<<16; - val2 |= (battle_get_agi(src)/10)&0xffff; + val2 = ((status_get_dex(src)/20)&0xffff)<<16; + val2 |= (status_get_agi(src)/10)&0xffff; break; case BA_POEMBRAGI: /* ƒuƒ‰ƒM‚ÌŽ */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON); - val2 = ((battle_get_dex(src)/10)&0xffff)<<16; - val2 |= (battle_get_int(src)/5)&0xffff; + val2 = ((status_get_dex(src)/10)&0xffff)<<16; + val2 |= (status_get_int(src)/5)&0xffff; break; case BA_APPLEIDUN: /* ƒCƒhƒDƒ“‚Ì—ÑŒç */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_NOENEMY; if(src->type == BL_PC) - val1 = ((pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON))&0xffff)<<16; - else - val1 = 0; - val1 |= (battle_get_vit(src))&0xffff; - val2 = 0;//‰ñ•œ—pƒ^ƒCƒ€ƒJƒEƒ“ƒ^(6•b?‚É1?‰Á) + val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)&0xffff; + val2 |= (status_get_vit(src))&0xffff; + val3 = 0;//‰ñ•œ—pƒ^ƒCƒ€ƒJƒEƒ“ƒ^(6•b?‚É1?‰Á) break; case DC_SERVICEFORYOU: /* ƒT?ƒrƒXƒtƒH?ƒ†? */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_PARTY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; - val2 = battle_get_int(src)/10; + val2 = status_get_int(src)/10; break; case BA_ASSASSINCROSS: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1; - val2 = battle_get_agi(src)/20; + val2 = status_get_agi(src)/20; break; case DC_FORTUNEKISS: /* K‰^‚̃LƒX */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; - val2 = battle_get_luk(src)/10; - break; - - case AM_DEMONSTRATION: /* ƒfƒ‚ƒ“ƒXƒgƒŒ?ƒVƒ‡ƒ“ */ - limit=skill_get_time(skillid,skilllv); - interval=1000; - range=1; - target=BCT_ENEMY; - break; - - case WE_CALLPARTNER: /* ‚ ‚È‚½‚Ɉ§‚¢‚½‚¢ */ - limit=skill_get_time(skillid,skilllv); - range=-1; - break; - - case HP_BASILICA: /* ƒoƒWƒŠƒJ */ - limit=skill_get_time(skillid,skilllv); - target=BCT_ALL; - range=3; - //Fix to prevent the priest from walking while Basilica is up. - battle_stopwalking(src,1); - //skill_status_change_start(src,SC_ANKLE,skilllv,0,0,0,limit,0); - //sd->canmove_tick = gettick() + limit; // added later [celest] - break; - - case PA_GOSPEL: /* ƒSƒXƒyƒ‹ */ - count=49; - target=BCT_PARTY; - limit=skill_get_time(skillid,skilllv); - break; - - case CG_MOONLIT: - range=1; - target=BCT_ALL; - limit=skill_get_time(skillid,skilllv); + val2 = status_get_luk(src)/10; break; case PF_FOGWALL: /* ƒtƒHƒOƒEƒH?ƒ‹ */ - count=15; - limit=skill_get_time(skillid,skilllv); - if(sc_data) { - if (sc_data[SC_DELUGE].timer!=-1) limit *= 2; - } + if(sc_data && sc_data[SC_DELUGE].timer!=-1) limit *= 2; break; case RG_GRAFFITI: /* Graffiti */ count=1; // Leave this at 1 [Valaris] - limit=600000; // Time length [Valaris] - break; - - case GD_LEADERSHIP: - case GD_GLORYWOUNDS: - case GD_SOULCOLD: - case GD_HAWKEYES: - range=2; - target=BCT_NOENEMY; - limit=600000; break; } - nullpo_retr(NULL, group=skill_initunitgroup(src,count,skillid,skilllv,skill_get_unit_id(skillid,flag&1))); + nullpo_retr(NULL, group=skill_initunitgroup(src,(count > 0 ? count : layout->count), + skillid,skilllv,skill_get_unit_id(skillid,flag&1))); group->limit=limit; group->val1=val1; group->val2=val2; + group->val3=val3; group->target_flag=target; group->interval=interval; - group->range=range; if(skillid==HT_TALKIEBOX || skillid==RG_GRAFFITI){ - group->valstr=calloc(80, 1); + group->valstr=(char *) aCallocA(80, 1); if(group->valstr==NULL){ printf("skill_castend_map: out of memory !\n"); exit(1); } memcpy(group->valstr,talkie_mes,80); } - for(i=0;i<count;i++){ + for(i=0;i<layout->count;i++){ struct skill_unit *unit; - int ux=x,uy=y,val1=skilllv,val2=0,limit=group->limit,alive=1; - int range=group->range; - switch(skillid){ /* Ý’è */ - case AL_PNEUMA: /* ƒjƒ…?ƒ} */ - { - static const int dx[9]={-1, 0, 1,-1, 0, 1,-1, 0, 1}; - static const int dy[9]={-1,-1,-1, 0, 0, 0, 1, 1, 1}; - ux+=dx[i]; - uy+=dy[i]; - } - break; + int ux,uy,val1=skilllv,val2=0,limit=group->limit,alive=1; + ux = x + layout->dx[i]; + uy = y + layout->dy[i]; + switch (skillid) { case MG_FIREWALL: /* ƒtƒ@ƒCƒ„?ƒEƒH?ƒ‹ */ - { - if(dir&1){ /* ŽÎ‚ß”z’u */ - static const int dx[][5]={ - { 1,1,0,0,-1 }, { -1,-1,0,0,1 }, - },dy[][5]={ - { 1,0,0,-1,-1 }, { 1,0,0,-1,-1 }, - }; - ux+=dx[(dir>>1)&1][i]; - uy+=dy[(dir>>1)&1][i]; - }else{ /* ㉺”z’u */ - if(dir%4==0) /* ㉺ */ - ux+=i-1; - else /* ¶‰E */ - uy+=i-1; - } - val2=group->val2; - } - break; - - case PR_SANCTUARY: /* ƒTƒ“ƒNƒ`ƒ…ƒAƒŠ */ - { - static const int dx[]={ - -1,0,1, -2,-1,0,1,2, -2,-1,0,1,2, -2,-1,0,1,2, -1,0,1 }; - static const int dy[]={ - -2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0, 1,1,1,1,1, 2,2,2, }; - ux+=dx[i]; - uy+=dy[i]; - } + val2=group->val2; break; - - case PR_MAGNUS: /* ƒ}ƒOƒkƒXƒGƒNƒ\ƒVƒYƒ€ */ - { - static const int dx[]={ -1,0,1, -1,0,1, -3,-2,-1,0,1,2,3, - -3,-2,-1,0,1,2,3, -3,-2,-1,0,1,2,3, -1,0,1, -1,0,1, }; - static const int dy[]={ - -3,-3,-3, -2,-2,-2, -1,-1,-1,-1,-1,-1,-1, - 0,0,0,0,0,0,0, 1,1,1,1,1,1,1, 2,2,2, 3,3,3 }; - ux+=dx[i]; - uy+=dy[i]; - } - break; - - case WZ_SIGHTRASHER: - { - static const int dx[]={ - -5, 0, 5, -4, 0, 4, -3, 0, 3, -2, 0, 2, -1, 0, 1, -5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, -1, 0, 1, -2, 0, 2, -3, 0, 3, -4, 0, 4, -5, 0, 5 }; - static const int dy[]={ - -5,-5,-5, -4,-4,-4, -3,-3,-3, -2,-2,-2, -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 }; - ux+=dx[i]; - uy+=dy[i]; - } - break; - case WZ_ICEWALL: /* ƒAƒCƒXƒEƒH?ƒ‹ */ - { - static const int dirx[8]={0,-1,-1,-1,0,1,1,1}; - static const int diry[8]={1,1,0,-1,-1,-1,0,1}; if(skilllv <= 1) val1 = 500; else val1 = 200 + 200*skilllv; - if(src->x == x && src->y == y) - dir = 2; - else - dir=map_calc_dir(src,x,y); - ux+=(2-i)*diry[dir]; - uy+=(i-2)*dirx[dir]; - } - break; - - case WZ_QUAGMIRE: /* ƒNƒ@ƒOƒ}ƒCƒA */ - ux+=(i%5-2); - uy+=(i/5-2); - if(i==12) - range=2; - else - range=-1; - - break; - - case AS_VENOMDUST: /* ƒxƒmƒ€ƒ_ƒXƒg */ - { - static const int dx[]={-1,0,0,0,1}; - static const int dy[]={0,-1,0,1,0}; - ux+=dx[i]; - uy+=dy[i]; - } - break; - - case CR_GRANDCROSS: /* ƒOƒ‰ƒ“ƒhƒNƒƒX */ - { - static const int dx[]={ - 0, 0, -1,0,1, -2,-1,0,1,2, -4,-3,-2,-1,0,1,2,3,4, -2,-1,0,1,2, -1,0,1, 0, 0, }; - static const int dy[]={ - -4, -3, -2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0,0,0,0,0, 1,1,1,1,1, 2,2,2, 3, 4, }; - ux+=dx[i]; - uy+=dy[i]; - } - break; - case SA_VOLCANO: /* ƒ{ƒ‹ƒP?ƒm */ - case SA_DELUGE: /* ƒfƒŠƒ…?ƒW */ - case SA_VIOLENTGALE: /* ƒoƒCƒIƒŒƒ“ƒgƒQƒCƒ‹ */ - { - int u_range=0,central=0; - if(skilllv<=2){ - u_range=2; - central=12; - }else if(skilllv<=4){ - u_range=3; - central=24; - }else if(skilllv>=5){ - u_range=4; - central=40; - } - ux+=(i%(u_range*2+1)-u_range); - uy+=(i/(u_range*2+1)-u_range); - - if(i==central) - range=u_range;//’†‰›‚̃†ƒjƒbƒg‚Ì?‰Ê”Í?‚Í‘S”Í? - else - range=-1;//’†‰›ˆÈŠO‚̃†ƒjƒbƒg‚Íü‚è - } - break; - case SA_LANDPROTECTOR: /* ƒ‰ƒ“ƒhƒvƒƒeƒNƒ^? */ - { - int u_range=0; - - if(skilllv<=2) u_range=3; - else if(skilllv<=4) u_range=4; - else if(skilllv>=5) u_range=5; - - ux+=(i%(u_range*2+1)-u_range); - uy+=(i/(u_range*2+1)-u_range); - - range=0; - } - break; - - /* ƒ_ƒ“ƒX‚È‚Ç */ - case BD_LULLABY: /* ŽqŽç‰Ì */ - case BD_RICHMANKIM: /* ƒjƒˆƒ‹ƒh‚̉ƒ */ - case BD_ETERNALCHAOS: /* ‰i‰“‚̬“× */ - case BD_DRUMBATTLEFIELD:/* ?‘¾ŒÛ‚Ì‹¿‚« */ - case BD_RINGNIBELUNGEN: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ - case BD_ROKISWEIL: /* ƒƒL‚Ì‹©‚Ñ */ - case BD_INTOABYSS: /* [•£‚Ì’†‚É */ - case BD_SIEGFRIED: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ - ux+=(i%9-4); - uy+=(i/9-4); - if(i==40) - range=4; /* ’†S‚Ìꇂ͔Í?‚ð4‚ɃI?ƒo?ƒ‰ƒCƒh */ - else - range=-1; /* ’†S‚¶‚á‚È‚¢ê‡‚Í”Í?‚ð-1‚ɃI?ƒo?ƒ‰ƒCƒh */ - break; - case BA_DISSONANCE: /* •s‹¦˜a‰¹ */ - case BA_WHISTLE: /* Œû“J */ - case BA_ASSASSINCROSS: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX */ - case BA_POEMBRAGI: /* ƒuƒ‰ƒM‚ÌŽ */ - case BA_APPLEIDUN: /* ƒCƒhƒDƒ“‚Ì—ÑŒç */ - case DC_UGLYDANCE: /* Ž©•ªŸŽè‚ȃ_ƒ“ƒX */ - case DC_HUMMING: /* ƒnƒ~ƒ“ƒO */ - case DC_DONTFORGETME: /* Ž„‚ð–Y‚ê‚È‚¢‚Åc */ - case DC_FORTUNEKISS: /* K‰^‚̃LƒX */ - case DC_SERVICEFORYOU: /* ƒT?ƒrƒXƒtƒH?ƒ†? */ - case CG_MOONLIT: - ux+=(i%7-3); - uy+=(i/7-3); - if(i==40) - range=4; /* ’†S‚Ìꇂ͔Í?‚ð4‚ɃI?ƒo?ƒ‰ƒCƒh */ - else - range=-1; /* ’†S‚¶‚á‚È‚¢ê‡‚Í”Í?‚ð-1‚ɃI?ƒo?ƒ‰ƒCƒh */ - break; - case PA_GOSPEL: /* ƒSƒXƒyƒ‹ */ - ux+=(i%7-3); - uy+=(i/7-3); - break; - case PF_FOGWALL: /* ƒtƒHƒOƒEƒH?ƒ‹ */ - ux+=(i%5-2); - uy+=(i/5-1); break; case RG_GRAFFITI: /* Graffiti [Valaris] */ ux+=(i%5-2); @@ -5647,7 +5400,7 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid, map_foreachinarea(skill_landprotector,src->m,ux,uy,ux,uy,BL_SKILL,skillid,&alive); if(skillid==WZ_ICEWALL && alive){ - val2=map_getcell(src->m,ux,uy); + val2=map_getcell(src->m,ux,uy,CELL_GETTYPE); if(val2==5 || val2==1) alive=0; else { @@ -5663,30 +5416,13 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid, unit->limit=limit; unit->range=range; - // [celest] - if (sc_data) { - // attach the unit's id to the caster - switch (skillid) { - case HP_BASILICA: - if (sc_data[SC_BASILICA].timer!=-1) - sc_data[SC_BASILICA].val4 = (int)unit; - break; - case GD_LEADERSHIP: - sc_data[SC_LEADERSHIP].val4 = (int)unit; - break; - case GD_GLORYWOUNDS: - sc_data[SC_GLORYWOUNDS].val4 = (int)unit; - break; - case GD_SOULCOLD: - sc_data[SC_SOULCOLD].val4 = (int)unit; - break; - case GD_HAWKEYES: - sc_data[SC_HAWKEYES].val4 = (int)unit; - break; - } - } + if (range==0 && active_flag) + map_foreachinarea(skill_unit_effect,unit->bl.m + ,unit->bl.x,unit->bl.y,unit->bl.x,unit->bl.y + ,0,&unit->bl,gettick(),1); } } + return group; } @@ -5698,126 +5434,245 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int { struct skill_unit_group *sg; struct block_list *ss; - struct skill_unit_group_tickset *ts; - struct map_session_data *srcsd=NULL; - int diff,goflag,splash_count=0; + struct skill_unit *unit2; + struct status_change *sc_data; + int type; nullpo_retr(0, src); nullpo_retr(0, bl); - - if( bl->prev==NULL || !src->alive || (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl) ) ) + + if(bl->prev==NULL || !src->alive || + (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))) return 0; nullpo_retr(0, sg=src->group); nullpo_retr(0, ss=map_id2bl(sg->src_id)); + + sc_data = status_get_sc_data(bl); + type = SkillStatusChangeTable[sg->skill_id]; - if(ss->type == BL_PC) - nullpo_retr(0, srcsd=(struct map_session_data *)ss); - if(srcsd && srcsd->chatID) + if (battle_check_target(&src->bl,bl,sg->target_flag)<=0) return 0; - if( bl->type!=BL_PC && bl->type!=BL_MOB ) + // ‘ÎÛ‚ªLPã‚É‹‚éꇂ͖³Œø + if (map_find_skill_unit_oncell(bl,bl->x,bl->y,SA_LANDPROTECTOR,NULL)) return 0; - nullpo_retr(0, ts=skill_unitgrouptickset_search( bl, sg->group_id)); - diff=DIFF_TICK(tick,ts->tick); - goflag=(diff>sg->interval || diff<0); - if (sg->skill_id == CR_GRANDCROSS && !battle_config.gx_allhit) // d‚È‚Á‚Ä‚¢‚½‚ç3HIT‚µ‚È‚¢ - goflag = (diff>sg->interval*map_count_oncell(bl->m,bl->x,bl->y) || diff<0); - //?Û‚ªLPã‚É‹‚éꇂ͖³? - map_foreachinarea(skill_landprotector,bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,0,&goflag); + switch (sg->unit_id) { + case 0x85: /* ƒjƒ…[ƒ} */ + case 0x7e: /* ƒZƒCƒtƒeƒBƒEƒH[ƒ‹ */ + if (sc_data && sc_data[type].timer == -1) + status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); + break; - if(!goflag) - return 0; - ts->tick=tick; - ts->group_id=sg->group_id; + case 0x80: /* ƒ[ƒvƒ|[ƒ^ƒ‹(”“®Œã) */ + if(bl->type==BL_PC){ + struct map_session_data *sd = (struct map_session_data *)bl; + if(sd && src->bl.m == bl->m && src->bl.x == bl->x && src->bl.y == bl->y && + src->bl.x == sd->to_x && src->bl.y == sd->to_y) { + if( battle_config.chat_warpportal || !sd->chatID ){ + pc_setpos(sd,sg->valstr,sg->val2>>16,sg->val2&0xffff,3); + if(sg->src_id == bl->id || (strcmp(map[src->bl.m].name,sg->valstr) == 0 && + src->bl.x == (sg->val2>>16) && src->bl.y == (sg->val2&0xffff) )) + skill_delunitgroup(sg); + if (--sg->val1<=0) + skill_delunitgroup(sg); + } + } + } else if(bl->type==BL_MOB && battle_config.mob_warpportal){ + int m = map_mapname2mapid(sg->valstr); + mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3); + } + break; - switch(sg->unit_id){ - case 0x83: /* ƒTƒ“ƒNƒ`ƒ…ƒAƒŠ */ - { - int race=battle_get_race(bl); - int damage_flag = (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6)? 1:0; + case 0x8e: /* ƒNƒ@ƒOƒ}ƒCƒA */ + if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + break; + if(sc_data && sc_data[type].timer==-1) + status_change_start(bl,type,sg->skill_lv,(int)src,0,0, + skill_get_time2(sg->skill_id,sg->skill_lv),0); + break; - if( battle_get_hp(bl)>=battle_get_max_hp(bl) && !damage_flag) + case 0x9a: /* ƒ{ƒ‹ƒP?ƒm */ + case 0x9b: /* ƒfƒŠƒ…?ƒW */ + case 0x9c: /* ƒoƒCƒIƒŒƒ“ƒgƒQƒCƒ‹ */ + if (sc_data && sc_data[type].timer!=-1) { + unit2 = (struct skill_unit *)sc_data[type].val4; + if (unit2 && unit2->group && + (unit2==src || DIFF_TICK(sg->tick,unit2->group->tick)<=0)) break; + } + status_change_start(bl,type,sg->skill_lv,(int)src,0,0, + skill_get_time2(sg->skill_id,sg->skill_lv),0); + break; - if((sg->val1--)<=0){ - skill_delunitgroup(sg); - return 0; - } - if(!damage_flag) { - int heal=sg->val2; - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage) - heal=0; /* ?‹à峃J?ƒhiƒq?ƒ‹—Ê‚Oj */ - clif_skill_nodamage(&src->bl,bl,AL_HEAL,heal,1); - battle_heal(NULL,bl,heal,0,0); - } - else - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + case 0x9e: /* ŽqŽç‰S */ + case 0x9f: /* ƒjƒˆƒ‹ƒh‚̉ƒ */ + case 0xa0: /* ‰i‰“‚̬“× */ + case 0xa1: /* ?‘¾ŒÛ‚Ì‹¿‚« */ + case 0xa2: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ + case 0xa3: /* ƒƒL‚Ì‹©‚Ñ */ + case 0xa4: /* [•£‚Ì’†‚É */ + case 0xa5: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ + case 0xa6: /* •s‹¦˜a‰¹ */ + case 0xa7: /* Œû“J */ + case 0xa8: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX */ + case 0xa9: /* ƒuƒ‰ƒM‚ÌŽ */ + case 0xaa: /* ƒCƒhƒDƒ“‚Ì—ÑŒç */ + case 0xab: /* Ž©•ªŸŽè‚ȃ_ƒ“ƒX */ + case 0xac: /* ƒnƒ~ƒ“ƒO */ + case 0xad: /* Ž„‚ð–Y‚ê‚È‚¢‚Åc */ + case 0xae: /* K‰^‚̃LƒX */ + case 0xaf: /* ƒT?ƒrƒXƒtƒH?ƒ†? */ + if (sg->src_id==bl->id) + break; + if (sc_data && sc_data[type].timer!=-1) { + unit2 = (struct skill_unit *)sc_data[type].val4; + if (unit2 && unit2->group && + (unit2 == src || DIFF_TICK(sg->tick,unit2->group->tick)<=0)) + break; } + status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, + (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); break; - case 0x84: /* ƒ}ƒOƒkƒXƒGƒNƒ\ƒVƒYƒ€ */ - { - int race=battle_get_race(bl); - int damage_flag = (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6)? 1:0; + case 0xb4: // Basilica + if (battle_check_target(&src->bl,bl,BCT_NOENEMY)>0) { + if (sc_data && sc_data[type].timer!=-1) { + struct skill_unit_group *sg2 = (struct skill_unit_group *)sc_data[type].val4; + if (sg2 && (sg2 == src->group || DIFF_TICK(sg->tick,sg2->tick)<=0)) + break; + } else + status_change_start(bl,type,sg->skill_lv,(int)src,0,0, + skill_get_time2(sg->skill_id,sg->skill_lv),0); + } else if (!status_get_mode(bl)&0x20) + skill_blown(&src->bl,bl,1); + break; - if(!damage_flag) - return 0; - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + case 0xb6: /* ƒtƒHƒOƒEƒH?ƒ‹ */ + if (sc_data && sc_data[type].timer!=-1) { + struct skill_unit_group *sg2 = (struct skill_unit_group *)sc_data[type].val4; + if (sg2 && (sg2 == src->group || DIFF_TICK(sg->tick,sg2->tick)<=0)) + break; } + status_change_start (bl, type, sg->skill_lv, sg->val1, sg->val2, (int)sg, + skill_get_time2(sg->skill_id, sg->skill_lv), 0); + if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0) + skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, tick); + break; + + case 0xb2: /* ‚ ‚È‚½‚ð_?‚¢‚½‚¢‚Å‚· */ + case 0xb3: /* ƒSƒXƒyƒ‹ */ + //‚Æ‚è‚ ‚¦‚¸‰½‚à‚µ‚È‚¢ break; + /* default: + if(battle_config.error_log) + printf("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); + break;*/ + } - case 0x85: /* ƒjƒ…?ƒ} */ + return 0; +} + +/*========================================== + * ƒXƒLƒ‹ƒ†ƒjƒbƒg‚Ì”“®ƒCƒxƒ“ƒg(ƒ^ƒCƒ}[”“®) + *------------------------------------------ + */ +int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsigned int tick) +{ + struct skill_unit_group *sg; + struct block_list *ss; + int splash_count=0; + struct status_change *sc_data; + struct skill_unit_group_tickset *ts; + int type; + int diff=0; + + nullpo_retr(0, src); + nullpo_retr(0, bl); + + if (bl->type!=BL_PC && bl->type!=BL_MOB) + return 0; + + if (bl->prev==NULL || !src->alive || + (bl->type==BL_PC && pc_isdead((struct map_session_data *)bl))) + return 0; + + nullpo_retr(0, sg=src->group); + nullpo_retr(0, ss=map_id2bl(sg->src_id)); + sc_data = status_get_sc_data(bl); + type = SkillStatusChangeTable[sg->skill_id]; + + // ‘ÎÛ‚ªLPã‚É‹‚éꇂ͖³Œø + if (map_find_skill_unit_oncell(bl,bl->x,bl->y,SA_LANDPROTECTOR,NULL)) + return 0; + + // ‘O‚ɉe‹¿‚ðŽó‚¯‚Ä‚©‚çinterval‚̊Ԃ͉e‹¿‚ðŽó‚¯‚È‚¢ + nullpo_retr(0,ts = skill_unitgrouptickset_search(bl,sg,tick)); + diff = DIFF_TICK(tick,ts->tick); + if (sg->skill_id == PR_SANCTUARY) + diff += 500; // V‹K‚ɉñ•œ‚µ‚½ƒ†ƒjƒbƒg‚¾‚¯ƒJƒEƒ“ƒg‚·‚邽‚߂̎dŠ|‚¯ + if (diff < 0) + return 0; + ts->tick = tick+sg->interval; + // GX‚Íd‚È‚Á‚Ä‚¢‚½‚ç3HIT‚µ‚È‚¢ + if (sg->skill_id==CR_GRANDCROSS && !battle_config.gx_allhit) + ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y)-1); + + switch (sg->unit_id) { + case 0x83: /* ƒTƒ“ƒNƒ`ƒ…ƒAƒŠ */ { - struct skill_unit *unit2; - struct status_change *sc_data=battle_get_sc_data(bl); - int type=SC_PNEUMA; - if(sc_data && sc_data[type].timer==-1) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); - else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){ - if(DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); - ts->tick-=sg->interval; - } + int race = status_get_race(bl); + + if (battle_check_undead(race, status_get_elem_type(bl)) || race==6) { + if (skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0)) { + // reduce healing count if this was meant for damaging [hekate] + sg->val1 -= 2; + //sg->val1--; // ƒ`ƒƒƒbƒgƒLƒƒƒ“ƒZƒ‹‚ɑΉž + } + } else { + int heal = sg->val2; + if (status_get_hp(bl) >= status_get_max_hp(bl)) + break; + if (bl->type == BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage) + heal = 0; /* ‰©‹à峃J[ƒhiƒq[ƒ‹—Ê‚Oj */ + clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); + battle_heal(NULL, bl, heal, 0, 0); + if (diff >= 500) + sg->val1--; // V‹K‚É“ü‚Á‚½ƒ†ƒjƒbƒg‚¾‚¯ƒJƒEƒ“ƒg + } + if (sg->val1 <= 0) + skill_delunitgroup(sg); + break; } - break; - case 0x7e: /* ƒZƒCƒtƒeƒBƒEƒH?ƒ‹ */ + + case 0x84: /* ƒ}ƒOƒkƒXƒGƒNƒ\ƒVƒYƒ€ */ { - struct skill_unit *unit2; - struct status_change *sc_data=battle_get_sc_data(bl); - int type=SC_SAFETYWALL; - if(sc_data && sc_data[type].timer==-1) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); - else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){ - if(sg->val1 < unit2->group->val1 ) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); - ts->tick-=sg->interval; - } + int race = status_get_race(bl); + if (!battle_check_undead(race,status_get_elem_type(bl)) && race!=6) + return 0; + skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + src->val2++; + break; } - break; - case 0x86: /* ƒ?ƒhƒIƒuƒ”ƒ@?ƒ~ƒŠƒIƒ“(•ƒXƒg?ƒ€ƒKƒXƒg •ƒOƒ‰ƒ“ƒhƒNƒƒX) */ + case 0x7f: /* ƒtƒ@ƒCƒ„[ƒEƒH[ƒ‹ */ skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - break; - - case 0x7f: /* ƒtƒ@ƒCƒ„?ƒEƒH?ƒ‹ */ - if( (src->val2--)>0) - skill_attack(BF_MAGIC,ss,&src->bl,bl, - sg->skill_id,sg->skill_lv,tick,0); - if( src->val2<=0 ) + if (--src->val2<=0) skill_delunit(src); break; - - case 0x87: /* ƒtƒ@ƒCƒA?ƒsƒ‰?(?“®‘O) */ + case 0x86: /* ƒ[ƒhƒIƒuƒ”ƒ@[ƒ~ƒŠƒIƒ“(TS,MS,FN,SG,HD,GX,ˆÅGX) */ + skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + break; + case 0x87: /* ƒtƒ@ƒCƒA[ƒsƒ‰[(”“®‘O) */ skill_delunit(src); skill_unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1); break; - case 0x88: /* ƒtƒ@ƒCƒA?ƒsƒ‰?(?“®Œã) */ - if(DIFF_TICK(tick,sg->tick) < 150) - //skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - map_foreachinarea(skill_attack_area,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,BF_MAGIC,ss,&src->bl,sg->skill_id,sg->skill_lv,tick,0,BCT_ENEMY); // area damage [Celest] + case 0x88: /* ƒtƒ@ƒCƒA[ƒsƒ‰[(”“®Œã) */ + map_foreachinarea(skill_attack_area,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0, + BF_MAGIC,ss,&src->bl,sg->skill_id,sg->skill_lv,tick,0,BCT_ENEMY); // area damage [Celest] + //skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; case 0x90: /* ƒXƒLƒbƒhƒgƒ‰ƒbƒv */ @@ -5830,7 +5685,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int clif_changelook(&src->bl,LOOK_BASE,sg->unit_id); sg->limit=DIFF_TICK(tick,sg->tick)+1500; } - break; + break; case 0x93: /* ƒ‰ƒ“ƒhƒ}ƒCƒ“ */ skill_attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); @@ -5859,20 +5714,22 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int break; case 0x91: /* ƒAƒ“ƒNƒ‹ƒXƒlƒA */ - { - struct status_change *sc_data=battle_get_sc_data(bl); - if(sg->val2==0 && sc_data && sc_data[SC_ANKLE].timer==-1){ + if(sg->val2==0 && sc_data && sc_data[SC_ANKLE].timer==-1){ int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE); - int sec=skill_get_time2(sg->skill_id,sg->skill_lv) - (double)battle_get_agi(bl)*0.1; - if(battle_get_mode(bl)&0x20) - sec = sec/5; - battle_stopwalking(bl,1); - skill_status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0); - + int sec = skill_get_time2(sg->skill_id,sg->skill_lv) - status_get_agi(bl)*100; + if(status_get_mode(bl)&0x20) + sec = sec/5; + if (sec < 3000) // minimum time of 3 seconds [celest] + sec = 3000; + battle_stopwalking(bl,1); + status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0); + + skill_unit_move(bl,tick,0); if(moveblock) map_delblock(bl); bl->x = src->bl.x; bl->y = src->bl.y; if(moveblock) map_addblock(bl); + skill_unit_move(bl,tick,1); if(bl->type == BL_MOB) clif_fixmobpos((struct mob_data *)bl); else if(bl->type == BL_PET) @@ -5880,129 +5737,26 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int else clif_fixpos(bl); clif_01ac(&src->bl); - sg->limit=DIFF_TICK(tick,sg->tick) + sec; + sg->limit=DIFF_TICK(tick,sg->tick) + sec; sg->val2=bl->id; - } + sg->interval = -1; + src->range = 0; } break; - case 0x80: /* ƒ?ƒvƒ|?ƒ^ƒ‹(?“®Œã) */ - if(bl->type==BL_PC){ - struct map_session_data *sd = (struct map_session_data *)bl; - if(sd && src->bl.m == bl->m && src->bl.x == bl->x && src->bl.y == bl->y && src->bl.x == sd->to_x && src->bl.y == sd->to_y) { - if( battle_config.chat_warpportal || !sd->chatID ){ - if((sg->val1--)>0){ - pc_setpos(sd,sg->valstr,sg->val2>>16,sg->val2&0xffff,3); - if(sg->src_id == bl->id ||( strcmp(map[src->bl.m].name,sg->valstr) == 0 && src->bl.x == (sg->val2>>16) && src->bl.y == (sg->val2&0xffff) )) - skill_delunitgroup(sg); - }else - skill_delunitgroup(sg); - } - } - }else if(bl->type==BL_MOB && battle_config.mob_warpportal){ - int m=map_mapname2mapid(sg->valstr); - struct mob_data *md; - md=(struct mob_data *)bl; - mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3); - } - break; - - case 0x8e: /* ƒNƒ@ƒOƒ}ƒCƒA */ - { - int type=SkillStatusChangeTable[sg->skill_id]; - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if( battle_get_sc_data(bl)[type].timer==-1 ) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - } - break; case 0x92: /* ƒxƒmƒ€ƒ_ƒXƒg */ - { - struct status_change *sc_data=battle_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if( sc_data && sc_data[type].timer==-1 ) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - } + if(sc_data && sc_data[type].timer==-1 ) + status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); break; - case 0x9a: /* ƒ{ƒ‹ƒP?ƒm */ - case 0x9b: /* ƒfƒŠƒ…?ƒW */ - case 0x9c: /* ƒoƒCƒIƒŒƒ“ƒgƒQƒCƒ‹ */ - { - struct skill_unit *unit2; - struct status_change *sc_data=battle_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sc_data && sc_data[type].timer==-1) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){ - if( DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - ts->tick-=sg->interval; - } - } break; - - case 0x9e: /* ŽqŽç‰S */ - case 0x9f: /* ƒjƒˆƒ‹ƒh‚̉ƒ */ - case 0xa0: /* ‰i‰“‚̬“× */ - case 0xa1: /* ?‘¾ŒÛ‚Ì‹¿‚« */ - case 0xa2: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ - case 0xa3: /* ƒƒL‚Ì‹©‚Ñ */ - case 0xa4: /* [•£‚Ì’†‚É */ - case 0xa5: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ - case 0xa6: /* •s‹¦˜a‰¹ */ - case 0xa7: /* Œû“J */ - case 0xa8: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX */ - case 0xa9: /* ƒuƒ‰ƒM‚ÌŽ */ - case 0xab: /* Ž©•ªŸŽè‚ȃ_ƒ“ƒX */ - case 0xac: /* ƒnƒ~ƒ“ƒO */ - case 0xad: /* Ž„‚ð–Y‚ê‚È‚¢‚Åc */ - case 0xae: /* K‰^‚̃LƒX */ - case 0xaf: /* ƒT?ƒrƒXƒtƒH?ƒ†? */ - case 0xb4: - case 0xb6: /* ƒtƒHƒOƒEƒH?ƒ‹ */ - { - struct skill_unit *unit2; - struct status_change *sc_data=battle_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sg->src_id == bl->id) - break; - if(sc_data) { - if (sc_data[type].timer==-1) - skill_status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - else if( (unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){ - if( unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - skill_status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - ts->tick-=sg->interval; - } - } - } break; - - case 0xaa: /* ƒCƒhƒDƒ“‚Ì—ÑŒç */ - { - struct skill_unit *unit2; - struct status_change *sc_data=battle_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sg->src_id == bl->id) - break; - if( sc_data && sc_data[type].timer==-1) - skill_status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - else if((unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){ - if( DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - skill_status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - ts->tick-=sg->interval; - } - } break; case 0xb1: /* ƒfƒ‚ƒ“ƒXƒgƒŒ?ƒVƒ‡ƒ“ */ skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); if(bl->type == BL_PC && rand()%100 < sg->skill_lv && battle_config.equipment_breaking) pc_breakweapon((struct map_session_data *)bl); break; - case 0x99: /* ƒg?ƒL?ƒ{ƒbƒNƒX */ - if(sg->src_id == bl->id) //Ž©•ª‚ª“¥‚ñ‚Å‚à?“®‚µ‚È‚¢ + + case 0x99: /* ƒg[ƒL[ƒ{ƒbƒNƒX */ + if(sg->src_id == bl->id) //Ž©•ª‚ª“¥‚ñ‚Å‚à”“®‚µ‚È‚¢ break; if(sg->val2==0){ clif_talkiebox(&src->bl,sg->valstr); @@ -6011,68 +5765,40 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int sg->limit=DIFF_TICK(tick,sg->tick)+5000; sg->val2=-1; //“¥‚ñ‚¾ } - break; - case 0xb2: /* ‚ ‚È‚½‚ð_?‚¢‚½‚¢‚Å‚· */ - case 0xb3: /* ƒSƒXƒyƒ‹ */ - //case 0xb6: /* ƒtƒHƒOƒEƒH?ƒ‹ */ - moved [celest] - //‚Æ‚è‚ ‚¦‚¸‰½‚à‚µ‚È‚¢ + break; + + // Basilica + case 0xb4: /* ƒoƒWƒŠƒJ */ + if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0 && + !(status_get_mode(bl)&0x20)) + skill_blown(&src->bl,bl,1); + if (sg->src_id==bl->id) + break; + if (battle_check_target(&src->bl,bl,BCT_NOENEMY)>0 && sc_data && sc_data[type].timer == -1) + status_change_start(bl,type,sg->skill_lv,(int)src,0,0, + skill_get_time2(sg->skill_id,sg->skill_lv),0); break; case 0xb7: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ if(sg->val2==0){ int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE); skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick); + skill_unit_move(bl,tick,0); if(moveblock) map_delblock(bl); - bl->x = (&src->bl)->x; - bl->y = (&src->bl)->y; + bl->x = src->bl.x; + bl->y = src->bl.y; if(moveblock) map_addblock(bl); - if(bl->type == BL_MOB) - clif_fixmobpos((struct mob_data *)bl); - else if(bl->type == BL_PET) - clif_fixpetpos((struct pet_data *)bl); - else - clif_fixpos(bl); - clif_01ac(&src->bl); - sg->limit=DIFF_TICK(tick,sg->tick) + skill_get_time2(sg->skill_id,sg->skill_lv); + skill_unit_move(bl,tick,1); + if(bl->type == BL_MOB) + clif_fixmobpos((struct mob_data *)bl); + else if(bl->type == BL_PET) + clif_fixpetpos((struct pet_data *)bl); + else + clif_fixpos(bl); + sg->limit = DIFF_TICK(tick,sg->tick)+skill_get_time2(sg->skill_id,sg->skill_lv); sg->val2=bl->id; - } - break; - - // New guild skills [Celest] - case 0xc1: // GD_LEADERSHIP - { - struct map_session_data *sd; - if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) && - sd->status.guild_id == srcsd->status.guild_id && - sd->sc_data[SC_LEADERSHIP].timer == -1 && !sd->sc_data[SC_LEADERSHIP].val4) - skill_status_change_start(bl,SC_LEADERSHIP,1,0,0,0,0,0 ); - } - break; - case 0xc2: // GD_GLORYWOUNDS - { - struct map_session_data *sd; - if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) && - sd->status.guild_id == srcsd->status.guild_id && - sd->sc_data[SC_GLORYWOUNDS].timer == -1 && !sd->sc_data[SC_GLORYWOUNDS].val4) - skill_status_change_start(bl,SC_GLORYWOUNDS,1,0,0,0,0,0 ); - } - break; - case 0xc3: // GD_SOULCOLD - { - struct map_session_data *sd; - if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) && - sd->status.guild_id == srcsd->status.guild_id && - sd->sc_data[SC_SOULCOLD].timer == -1 && !sd->sc_data[SC_SOULCOLD].val4) - skill_status_change_start(bl,SC_SOULCOLD,1,0,0,0,0,0 ); - } - break; - case 0xc4: // GD_HAWKEYES - { - struct map_session_data *sd; - if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) && - sd->status.guild_id == srcsd->status.guild_id && - sd->sc_data[SC_HAWKEYES].timer == -1 && !sd->sc_data[SC_HAWKEYES].val4) - skill_status_change_start(bl,SC_HAWKEYES,1,0,0,0,0,0 ); + sg->interval = -1; + src->range = 0; } break; @@ -6081,6 +5807,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int printf("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); break;*/ } + if(bl->type==BL_MOB && ss!=bl) /* ƒXƒLƒ‹Žg—p?Œ‚ÌMOBƒXƒLƒ‹ */ { if(battle_config.mob_changetarget_byskill == 1) @@ -6104,85 +5831,55 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int tick) { struct skill_unit_group *sg; + struct status_change *sc_data; + int type; nullpo_retr(0, src); nullpo_retr(0, bl); nullpo_retr(0, sg=src->group); + sc_data = status_get_sc_data(bl); + type = SkillStatusChangeTable[sg->skill_id]; - if( bl->prev==NULL || !src->alive ) - return 0; - - if( bl->type!=BL_PC && bl->type!=BL_MOB ) + if (bl->prev==NULL || !src->alive || + (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))) return 0; switch(sg->unit_id){ - case 0x7e: /* ƒZƒCƒtƒeƒBƒEƒH?ƒ‹ */ - case 0x85: /* ƒjƒ…?ƒ} */ + case 0x7e: /* ƒZƒCƒtƒeƒBƒEƒH[ƒ‹ */ + case 0x85: /* ƒjƒ…[ƒ} */ case 0x8e: /* ƒNƒ@ƒOƒ}ƒCƒA */ - { - struct status_change *sc_data=battle_get_sc_data(bl); - int type= - (sg->unit_id==0x85)?SC_PNEUMA: - ((sg->unit_id==0x7e)?SC_SAFETYWALL: - SC_QUAGMIRE); - if((type != SC_QUAGMIRE || bl->type != BL_MOB) && - sc_data && sc_data[type].timer!=-1 && ((struct skill_unit *)sc_data[type].val2)==src){ - skill_status_change_end(bl,type,-1); - } - } break; - - case 0x91: /* ƒAƒ“ƒNƒ‹ƒXƒlƒA */ - { - struct block_list *target=map_id2bl(sg->val2); - if( target && target==bl ){ - skill_status_change_end(bl,SC_ANKLE,-1); - sg->limit=DIFF_TICK(tick,sg->tick)+1000; - } - } - break; - case 0xb5: - case 0xb8: - { - struct block_list *target=map_id2bl(sg->val2); - if( target==bl ) - skill_status_change_end(bl,SC_SPIDERWEB,-1); - sg->limit=DIFF_TICK(tick,sg->tick)+1000; + case 0x9a: /* ƒ{ƒ‹ƒP[ƒm */ + case 0x9b: /* ƒfƒŠƒ…[ƒW */ + case 0x9c: /* ƒoƒCƒIƒŒƒ“ƒgƒQƒCƒ‹ */ + if (type==SC_QUAGMIRE && bl->type==BL_MOB) + break; + if (sc_data && sc_data[type].timer!=-1 && sc_data[type].val2==(int)src) { + status_change_end(bl,type,-1); } break; - case 0xb6: - { - struct block_list *target=map_id2bl(sg->val2); - struct status_change *sc_data=battle_get_sc_data(bl); - if( target==bl ) { - skill_status_change_end(bl,SC_FOGWALL,-1); - if (sc_data && sc_data[SC_BLIND].timer!=-1) - sc_data[SC_BLIND].timer = add_timer( - gettick() + 30000, skill_status_change_timer, bl->id, 0); - } + case 0x91: /* ƒAƒ“ƒNƒ‹ƒXƒlƒA */ + { + struct block_list *target = map_id2bl(sg->val2); + if(target && target == bl){ + status_change_end(bl,SC_ANKLE,-1); sg->limit=DIFF_TICK(tick,sg->tick)+1000; } break; - case 0x9a: /* ƒ{ƒ‹ƒP?ƒm */ - case 0x9b: /* ƒfƒŠƒ…?ƒW */ - case 0x9c: /* ƒoƒCƒIƒŒƒ“ƒgƒQƒCƒ‹ */ - { - struct status_change *sc_data=battle_get_sc_data(bl); - struct skill_unit *su; - int type=SkillStatusChangeTable[sg->skill_id]; - if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val2)) && su == src ){ - skill_status_change_end(bl,type,-1); - } - } - break; - + } case 0x9e: /* ŽqŽç‰S */ case 0x9f: /* ƒjƒˆƒ‹ƒh‚̉ƒ */ case 0xa0: /* ‰i‰“‚̬“× */ - case 0xa1: /* ?‘¾ŒÛ‚Ì‹¿‚« */ - case 0xa2: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ + case 0xa1: /* 푾ŒÛ‚Ì‹¿‚« */ + case 0xa2: /* ƒj[ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ case 0xa3: /* ƒƒL‚Ì‹©‚Ñ */ case 0xa4: /* [•£‚Ì’†‚É */ - case 0xa5: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ + case 0xa5: /* •sŽ€g‚̃W[ƒNƒtƒŠ[ƒh */ + case 0xad: /* Ž„‚ð–Y‚ê‚È‚¢‚Åc */ + if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)src) { + status_change_end(bl,type,-1); + } + break; + case 0xa6: /* •s‹¦˜a‰¹ */ case 0xa7: /* Œû“J */ case 0xa8: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX */ @@ -6190,123 +5887,94 @@ int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int t case 0xaa: /* ƒCƒhƒDƒ“‚Ì—ÑŒç */ case 0xab: /* Ž©•ªŸŽè‚ȃ_ƒ“ƒX */ case 0xac: /* ƒnƒ~ƒ“ƒO */ - case 0xad: /* Ž„‚ð–Y‚ê‚È‚¢‚Åc */ case 0xae: /* K‰^‚̃LƒX */ case 0xaf: /* ƒT?ƒrƒXƒtƒH?ƒ†? */ - case 0xb4: - { - struct status_change *sc_data=battle_get_sc_data(bl); - struct skill_unit *su; - int type=SkillStatusChangeTable[sg->skill_id]; - if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val4)) && su == src ){ - skill_status_change_end(bl,type,-1); - } - } - break; - case 0xb7: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ - { - struct block_list *target=map_id2bl(sg->val2); - if( target && target==bl ) - skill_status_change_end(bl,SC_SPIDERWEB,-1); - sg->limit=DIFF_TICK(tick,sg->tick)+1000; + if (sg->src_id==bl->id) { + status_change_end(bl,type,-1); + break; } - break; - // New guild skills [Celest] - case 0xc1: // GD_LEADERSHIP - { - struct status_change *sc_data=battle_get_sc_data(bl); - if (sc_data && sc_data[SC_LEADERSHIP].timer != -1) - skill_status_change_end(bl,SC_LEADERSHIP,-1); + if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)src) { + sc_data[type].timer = add_timer(20000+tick, status_change_timer, bl->id, type); } - break; - case 0xc2: // GD_GLORYWOUNDS - { - struct status_change *sc_data=battle_get_sc_data(bl); - if (sc_data && sc_data[SC_GLORYWOUNDS].timer != -1) - skill_status_change_end(bl,SC_GLORYWOUNDS,-1); + break; + + case 0xb4: // Basilica + if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)sg) { + status_change_end(bl,type,-1); } break; - case 0xc3: // GD_SOULCOLD + + case 0xb6: { - struct status_change *sc_data=battle_get_sc_data(bl); - if (sc_data && sc_data[SC_SOULCOLD].timer != -1) - skill_status_change_end(bl,SC_SOULCOLD,-1); + if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)sg) { + status_change_end(bl,SC_FOGWALL,-1); + if (sc_data && sc_data[SC_BLIND].timer!=-1) + sc_data[SC_BLIND].timer = add_timer( + gettick() + 30000, status_change_timer, bl->id, 0); + } + break; } - break; - case 0xc4: // GD_HAWKEYES + + case 0xb7: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ { - struct status_change *sc_data=battle_get_sc_data(bl); - if (sc_data && sc_data[SC_HAWKEYES].timer != -1) - skill_status_change_end(bl,SC_HAWKEYES,-1); + struct block_list *target = map_id2bl(sg->val2); + if (target && target==bl) + status_change_end(bl,SC_SPIDERWEB,-1); + sg->limit = DIFF_TICK(tick,sg->tick)+1000; + break; } - break; /* default: if(battle_config.error_log) printf("skill_unit_onout: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); break;*/ } - skill_unitgrouptickset_delete(bl,sg->group_id); + return 0; } + /*========================================== - * ƒXƒLƒ‹ƒ†ƒjƒbƒg‚Ì휃Cƒxƒ“ƒg + * ƒXƒLƒ‹ƒ†ƒjƒbƒgŒø‰Ê”“®/—£’Eˆ—(foreachinarea) + * bl: ƒ†ƒjƒbƒg(BL_PC/BL_MOB) *------------------------------------------ */ -int skill_unit_ondelete(struct skill_unit *src,struct block_list *bl,unsigned int tick) +int skill_unit_effect(struct block_list *bl,va_list ap) { - struct skill_unit_group *sg; + struct skill_unit *unit; + struct skill_unit_group *group; + int flag; + unsigned int tick; + static int called = 0; - nullpo_retr(0, src); nullpo_retr(0, bl); - nullpo_retr(0, sg = src->group); + nullpo_retr(0, ap); + nullpo_retr(0, unit=va_arg(ap,struct skill_unit*)); + tick = va_arg(ap,unsigned int); + flag = va_arg(ap,unsigned int); - if( bl->prev==NULL || !src->alive ) + if (bl->type!=BL_PC && bl->type!=BL_MOB) return 0; - if( bl->type!=BL_PC && bl->type!=BL_MOB ) + if (!unit->alive || bl->prev==NULL) return 0; - switch(sg->unit_id){ - case 0x85: /* ƒjƒ…?ƒ} */ - case 0x7e: /* ƒZƒCƒtƒeƒBƒEƒH?ƒ‹ */ - case 0x8e: /* ƒNƒ@ƒOƒ}ƒCƒ„ */ - case 0x9a: /* ƒ{ƒ‹ƒP?ƒm */ - case 0x9b: /* ƒfƒŠƒ…?ƒW */ - case 0x9c: /* ƒoƒCƒIƒŒƒ“ƒgƒQƒCƒ‹ */ - case 0x9e: /* ŽqŽç‰S */ - case 0x9f: /* ƒjƒˆƒ‹ƒh‚̉ƒ */ - case 0xa0: /* ‰i‰“‚̬“× */ - case 0xa1: /* ?‘¾ŒÛ‚Ì‹¿‚« */ - case 0xa2: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ - case 0xa3: /* ƒƒL‚Ì‹©‚Ñ */ - case 0xa4: /* [•£‚Ì’†‚É */ - case 0xa5: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ - case 0xa6: /* •s‹¦˜a‰¹ */ - case 0xa7: /* Œû“J */ - case 0xa8: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX */ - case 0xa9: /* ƒuƒ‰ƒM‚ÌŽ */ - case 0xaa: /* ƒCƒhƒDƒ“‚Ì—ÑŒç */ - case 0xab: /* Ž©•ªŸŽè‚ȃ_ƒ“ƒX */ - case 0xac: /* ƒnƒ~ƒ“ƒO */ - case 0xad: /* Ž„‚ð–Y‚ê‚È‚¢‚Åc */ - case 0xae: /* K‰^‚̃LƒX */ - case 0xaf: /* ƒT?ƒrƒXƒtƒH?ƒ†? */ - case 0xb4: - case 0xc1: - case 0xc2: - case 0xc3: - case 0xc4: - return skill_unit_onout(src,bl,tick); + nullpo_retr(0, group=unit->group); -/* default: - if(battle_config.error_log) - printf("skill_unit_ondelete: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); - break;*/ + if (flag) + skill_unit_onplace(unit,bl,tick); + else { + skill_unit_onout(unit,bl,tick); + unit = map_find_skill_unit_oncell(bl,bl->x,bl->y,group->skill_id,unit); + if (unit && called == 0) { + called = 1; + skill_unit_onplace(unit,bl,tick); + called = 0; + } } - skill_unitgrouptickset_delete(bl,sg->group_id); + return 0; } + /*========================================== * ƒXƒLƒ‹ƒ†ƒjƒbƒg‚ÌŒÀŠEƒCƒxƒ“ƒg *------------------------------------------ @@ -6314,7 +5982,6 @@ int skill_unit_ondelete(struct skill_unit *src,struct block_list *bl,unsigned in int skill_unit_onlimit(struct skill_unit *src,unsigned int tick) { struct skill_unit_group *sg; - nullpo_retr(0, src); nullpo_retr(0, sg=src->group); @@ -6326,7 +5993,7 @@ int skill_unit_onlimit(struct skill_unit *src,unsigned int tick) src->bl.x,src->bl.y,1); if(group == NULL) return 0; - group->valstr=calloc(24, 1); + group->valstr=(char *) aCallocA(24, 1); if(group->valstr==NULL){ printf("skill_unit_onlimit: out of memory !\n"); exit(1); @@ -6344,7 +6011,7 @@ int skill_unit_onlimit(struct skill_unit *src,unsigned int tick) { struct map_session_data *sd = NULL; struct map_session_data *p_sd = NULL; - if((sd = (struct map_session_data *)(map_id2bl(sg->src_id))) == NULL) + if((sd = map_id2sd(sg->src_id)) == NULL) return 0; if((p_sd = pc_get_partner(sd)) == NULL) return 0; @@ -6352,38 +6019,6 @@ int skill_unit_onlimit(struct skill_unit *src,unsigned int tick) pc_setpos(p_sd,map[src->bl.m].name,src->bl.x,src->bl.y,3); } break; - case 0xc1: // GD_LEADERSHIP - { - struct map_session_data *sd; - if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) { - sd->sc_data[SC_LEADERSHIP].val4 = 0; - } - } - break; - case 0xc2: // GD_GLORYWOUNDS - { - struct map_session_data *sd; - if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) { - sd->sc_data[SC_GLORYWOUNDS].val4 = 0; - } - } - break; - case 0xc3: // GD_SOULCOLD - { - struct map_session_data *sd; - if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) { - sd->sc_data[SC_SOULCOLD].val4 = 0; - } - } - break; - case 0xc4: // GD_HAWKEYES - { - struct map_session_data *sd; - if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) { - sd->sc_data[SC_HAWKEYES].val4 = 0; - } - } - break; } return 0; } @@ -6444,10 +6079,7 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) return 0; } - if(battle_config.pc_skill_reiteration == 0) { - range = -1; - switch(sd->skillid) { - case MG_SAFETYWALL: + /*case MG_SAFETYWALL: case WZ_FIREPILLAR: case HT_SKIDTRAP: case HT_LANDMINE: @@ -6460,28 +6092,23 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) case HT_CLAYMORETRAP: case HT_TALKIEBOX: case AL_WARP: - case PF_SPIDERWEB: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ - case RG_GRAFFITI: /* ƒOƒ‰ƒtƒBƒeƒB */ + case PF_SPIDERWEB: + case RG_GRAFFITI: range = 0; break; case AL_PNEUMA: range = 1; - break; - } - if(range >= 0) { - if(skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,range,sd->skillid) > 0) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } + break;*/ + if (!battle_config.pc_skill_reiteration && + skill_get_unit_flag(sd->skillid)&UF_NOREITERATION && + skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,sd->skillid,sd->skilllv)) { + clif_skill_fail(sd,sd->skillid,0,0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; } - if(battle_config.pc_skill_nofootset) { - range = -1; - switch(sd->skillid) { - case WZ_FIREPILLAR: + /*case WZ_FIREPILLAR: case HT_SKIDTRAP: case HT_LANDMINE: case HT_ANKLESNARE: @@ -6492,25 +6119,22 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) case HT_BLASTMINE: case HT_CLAYMORETRAP: case HT_TALKIEBOX: - case PF_SPIDERWEB: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ + case PF_SPIDERWEB: case WZ_ICEWALL: - range = 1; + range = 2; break; case AL_WARP: range = 0; - break; - } - if(range >= 0) { - if(skill_check_unit_range2(sd->bl.m,sd->skillx,sd->skilly,range) > 0) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } + break;*/ + if (battle_config.pc_skill_nofootset && + skill_get_unit_flag(sd->skillid)&UF_NOFOOTSET && + skill_check_unit_range2(&sd->bl,sd->bl.m,sd->skillx,sd->skilly,sd->skillid,sd->skilllv)) { + clif_skill_fail(sd,sd->skillid,0,0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; } - if(battle_config.pc_land_skill_limit) { maxcount = skill_get_maxcount(sd->skillid); if(maxcount > 0) { @@ -6532,7 +6156,7 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) if(sd->skilllv <= 0) return 0; range = skill_get_range(sd->skillid,sd->skilllv); if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); + range = status_get_range(&sd->bl) - (range + 1); range += battle_config.pc_skill_add_range; if(battle_config.skill_out_range_consume) { // changed to allow casting when target walks out of range [Valaris] if(range < distance(sd->bl.x,sd->bl.y,sd->skillx,sd->skilly)) { @@ -6589,14 +6213,14 @@ static int skill_check_condition_char_sub(struct block_list *bl,va_list ap) nullpo_retr(0, c=va_arg(ap,int *)); nullpo_retr(0, ssd=(struct map_session_data*)src); - s_class = pc_calc_base_job(sd->status.class); + s_class = pc_calc_base_job(sd->status.class_); //ƒ`ƒFƒbƒN‚µ‚È‚¢Ý’è‚È‚çc‚É‚ ‚肦‚È‚¢‘å‚«‚È?Žš‚ð•Ô‚µ‚ÄI—¹ if(!battle_config.player_skill_partner_check){ //–{?‚Íforeach‚Ì‘O‚É‚â‚肽‚¢‚¯‚ÇÝ’è“K—p‰ÓŠ‚ð‚܂Ƃ߂邽‚߂ɂ±‚±‚Ö (*c)=99; return 0; } - ss_class = pc_calc_base_job(ssd->status.class); + ss_class = pc_calc_base_job(ssd->status.class_); switch(ssd->skillid){ case PR_BENEDICTIO: /* ¹?~•Ÿ */ @@ -6650,24 +6274,25 @@ static int skill_check_condition_use_sub(struct block_list *bl,va_list ap) nullpo_retr(0, c=va_arg(ap,int *)); nullpo_retr(0, ssd=(struct map_session_data*)src); - s_class = pc_calc_base_job(sd->status.class); - + s_class = pc_calc_base_job(sd->status.class_); + //ƒ`ƒFƒbƒN‚µ‚È‚¢Ý’è‚È‚çc‚É‚ ‚肦‚È‚¢‘å‚«‚È?Žš‚ð•Ô‚µ‚ÄI—¹ if(!battle_config.player_skill_partner_check){ //–{?‚Íforeach‚Ì‘O‚É‚â‚肽‚¢‚¯‚ÇÝ’è“K—p‰ÓŠ‚ð‚܂Ƃ߂邽‚߂ɂ±‚±‚Ö (*c)=99; return 0; } - ss_class = pc_calc_base_job(ssd->status.class); + ss_class = pc_calc_base_job(ssd->status.class_); skillid=ssd->skillid; skilllv=ssd->skilllv; - if(skilllv <= 0) return 0; + //if(skilllv <= 0) return 0; + if(skillid > 0 && skilllv <= 0) return 0; // celest switch(skillid){ case PR_BENEDICTIO: /* ¹?~•Ÿ */ if(sd != ssd && (s_class.job == 4 || s_class.job == 8 || s_class.job == 15) && (sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1) && sd->status.sp >= 10){ sd->status.sp -= 10; - pc_calcstatus(sd,0); + status_calc_pc(sd,0); (*c)++; } break; @@ -6692,7 +6317,7 @@ static int skill_check_condition_use_sub(struct block_list *bl,va_list ap) ){ ssd->sc_data[SC_DANCING].val4=bl->id; clif_skill_nodamage(bl,src,skillid,skilllv,1); - skill_status_change_start(bl,SC_DANCING,skillid,ssd->sc_data[SC_DANCING].val2,0,src->id,skill_get_time(skillid,skilllv)+1000,0); + status_change_start(bl,SC_DANCING,skillid,ssd->sc_data[SC_DANCING].val2,0,src->id,skill_get_time(skillid,skilllv)+1000,0); sd->skillid_dance=sd->skillid=skillid; sd->skilllv_dance=sd->skilllv=skilllv; (*c)++; @@ -6718,7 +6343,7 @@ static int skill_check_condition_mob_master_sub(struct block_list *bl,va_list ap nullpo_retr(0, mob_class=va_arg(ap,int)); nullpo_retr(0, c=va_arg(ap,int *)); - if(md->class==mob_class && md->master_id==src_id) + if(md->class_==mob_class && md->master_id==src_id) (*c)++; return 0; } @@ -6731,6 +6356,7 @@ int skill_check_condition(struct map_session_data *sd,int type) { int i,hp,sp,hp_rate,sp_rate,zeny,weapon,state,spiritball,skill,lv,mhp; int index[10],itemid[10],amount[10]; + int arrow_flag = 0; nullpo_retr(0, sd); @@ -6769,7 +6395,7 @@ int skill_check_condition(struct map_session_data *sd,int type) clif_skill_fail(sd,sd->skillid,0,0); return 0; } - if(sd->sc_data){ + if(sd->sc_count){ if( sd->sc_data[SC_DIVINA].timer!=-1 || sd->sc_data[SC_ROKISWEIL].timer!=-1 || (sd->sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) || @@ -6778,11 +6404,13 @@ int skill_check_condition(struct map_session_data *sd,int type) (sd->sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE)){ clif_skill_fail(sd,sd->skillid,0,0); return 0; /* ?‘ÔˆÙí‚â’¾?‚È‚Ç */ - } + } } skill = sd->skillid; lv = sd->skilllv; if(lv <= 0) return 0; + // for the guild skills [celest] + if (skill >= 10000 && skill < 10015) skill-= 9500; hp=skill_get_hp(skill, lv); /* Á”ïHP */ sp=skill_get_sp(skill, lv); /* Á”ïSP */ if((sd->skillid_old == BD_ENCORE) && skill==sd->skillid_dance) @@ -6854,6 +6482,10 @@ int skill_check_condition(struct map_session_data *sd,int type) } else sd->spiritball_old = lv; break; + case MO_BODYRELOCATION: + if (sd->sc_count && sd->sc_data[SC_EXPLOSIONSPIRITS].timer!=-1) + spiritball = 0; + break; case MO_CHAINCOMBO: //˜A‘Ŷ if(sd->sc_data[SC_BLADESTOP].timer==-1){ if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_TRIPLEATTACK) @@ -6865,7 +6497,7 @@ int skill_check_condition(struct map_session_data *sd,int type) return 0; break; case CH_TIGERFIST: //•šŒÕŒ - if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH) + if((sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH) && !sd->state.skill_flag) return 0; break; case CH_CHAINCRUSH: //˜A’Œ•ö? @@ -6916,8 +6548,9 @@ int skill_check_condition(struct map_session_data *sd,int type) case AM_SPHEREMINE: /* ƒXƒtƒBƒA?ƒ}ƒCƒ“ */ if(type&1){ int c=0; - int maxcount=skill_get_maxcount(skill); - int mob_class=(skill==AM_CANNIBALIZE)?1118:1142; + int summons[5] = { 1020, 1068, 1118, 1500, 1368 }; + int maxcount = (skill==AM_CANNIBALIZE)? 6-lv : skill_get_maxcount(skill); + int mob_class = (skill==AM_CANNIBALIZE)? summons[lv-1] :1142; if(battle_config.pc_land_skill_limit && maxcount>0) { map_foreachinarea(skill_check_condition_mob_master_sub ,sd->bl.m, 0, 0, map[sd->bl.m].xs, map[sd->bl.m].ys, BL_MOB, sd->bl.id, mob_class,&c ); if(c >= maxcount){ @@ -6929,7 +6562,7 @@ int skill_check_condition(struct map_session_data *sd,int type) break; case MG_FIREWALL: /* ƒtƒ@ƒCƒA?ƒEƒH?ƒ‹ */ case WZ_QUAGMIRE: - case WZ_FIREPILLAR: // celest + case WZ_FIREPILLAR: // celest case PF_FOGWALL: /* ?§ŒÀ */ if(battle_config.pc_land_skill_limit) { @@ -6947,6 +6580,29 @@ int skill_check_condition(struct map_session_data *sd,int type) } } break; + // skills require arrows as of 12/07 [celest] + case AC_DOUBLE: + case AC_SHOWER: + case AC_CHARGEARROW: + case BA_MUSICALSTRIKE: + case DC_THROWARROW: + case SN_SHARPSHOOTING: + case CG_ARROWVULCAN: + if(sd->equip_index[10] < 0) { + clif_arrow_fail(sd,0); + return 0; + } + arrow_flag = 1; + break; + case RG_BACKSTAP: + if(sd->status.weapon == 11) { + if (sd->equip_index[10] < 0) { + clif_arrow_fail(sd,0); + return 0; + } + arrow_flag = 1; + } + break; } if(!(type&2)){ @@ -7022,6 +6678,9 @@ int skill_check_condition(struct map_session_data *sd,int type) } break; case ST_EXPLOSIONSPIRITS: + if (skill == MO_EXTREMITYFIST && ((sd->sc_data[SC_COMBO].timer != -1 && (sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sd->sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) || sd->sc_data[SC_BLADESTOP].timer!=-1)) { + break; + } if(sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1) { clif_skill_fail(sd,skill,0,0); return 0; @@ -7043,7 +6702,7 @@ int skill_check_condition(struct map_session_data *sd,int type) } break; case ST_WATER: - if(map_getcell(sd->bl.m,sd->bl.x,sd->bl.y) != 3 && (sd->sc_data[SC_DELUGE].timer==-1)){ //…ê”»’è + if((!map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER))&& (sd->sc_data[SC_DELUGE].timer==-1)){ //…ê”»’è clif_skill_fail(sd,skill,0,0); return 0; } @@ -7060,8 +6719,9 @@ int skill_check_condition(struct map_session_data *sd,int type) if(((itemid[i] >= 715 && itemid[i] <= 717) || itemid[i] == 1065) && sd->sc_data[SC_INTOABYSS].timer != -1) continue; if(skill == WZ_FIREPILLAR && lv<=5) - continue; // no gemstones for 1-5 [Celest] - if(skill == AM_POTIONPITCHER && i != x) + continue; // no gemstones for 1-5 [Celest] + if((skill == AM_POTIONPITCHER || + skill == CR_SLIMPITCHER) && i != x) continue; index[i] = pc_search_inventory(sd,itemid[i]); @@ -7077,13 +6737,17 @@ int skill_check_condition(struct map_session_data *sd,int type) if(!(type&1)) return 1; - if(skill != AM_POTIONPITCHER) { + if(skill != AM_POTIONPITCHER && + skill != CR_SLIMPITCHER && + skill != MG_STONECURSE) { if(skill == AL_WARP && !(type&2)) return 1; for(i=0;i<10;i++) { if(index[i] >= 0) pc_delitem(sd,index[i],amount[i],0); // ƒAƒCƒeƒ€Á”ï } + if (arrow_flag && battle_config.arrow_decrement) + pc_delitem(sd,sd->equip_index[10],1,0); } if(type&2) @@ -7112,56 +6776,50 @@ int skill_check_condition(struct map_session_data *sd,int type) */ int skill_castfix( struct block_list *bl, int time ) { - struct map_session_data *sd; + struct map_session_data *sd = NULL; struct mob_data *md; // [Valaris] struct status_change *sc_data; - int dex; int castrate=100; - int skill,lv,castnodex; + int skill,lv; nullpo_retr(0, bl); if(bl->type==BL_MOB){ // Crash fix [Valaris] - md=(struct mob_data*)bl; + nullpo_retr(0, md=(struct mob_data*)bl); skill = md->skillid; lv = md->skilllv; - } - - else { - sd=(struct map_session_data*)bl; + } else { + nullpo_retr(0, sd=(struct map_session_data*)bl); skill = sd->skillid; lv = sd->skilllv; } if(lv <= 0) return 0; - sc_data = battle_get_sc_data(bl); - dex=battle_get_dex(bl); + sc_data = status_get_sc_data(bl); if (skill > MAX_SKILL_DB || skill < 0) return 0; - castnodex=skill_get_castnodex(skill, lv); + /* ƒTƒtƒ‰ƒMƒEƒ€ */ + if(sc_data && sc_data[SC_SUFFRAGIUM].timer!=-1 ) + time=time*(100-sc_data[SC_SUFFRAGIUM].val1*15)/100; + status_change_end( bl, SC_SUFFRAGIUM, -1); if(time==0) return 0; - if(castnodex > 0 && bl->type==BL_PC) - castrate=((struct map_session_data *)bl)->castrate; - else if (castnodex <= 0 && bl->type==BL_PC) { - castrate=((struct map_session_data *)bl)->castrate; - time=time*castrate*(battle_config.castrate_dex_scale - dex)/(battle_config.castrate_dex_scale * 100); - time=time*battle_config.cast_rate/100; + if (sd) { + if(!skill_get_castnodex(skill, lv) > 0) { + castrate=((struct map_session_data *)bl)->castrate; + time=time*castrate*(battle_config.castrate_dex_scale - status_get_dex(bl))/(battle_config.castrate_dex_scale * 100); + time=time*battle_config.cast_rate/100; + } } - /* ƒTƒtƒ‰ƒMƒEƒ€ */ - if(sc_data && sc_data[SC_SUFFRAGIUM].timer!=-1 ){ - time=time*(100-sc_data[SC_SUFFRAGIUM].val1*15)/100; - skill_status_change_end( bl, SC_SUFFRAGIUM, -1); - } /* ƒuƒ‰ƒM‚ÌŽ */ - if(sc_data && sc_data[SC_POEMBRAGI].timer!=-1 ) + if(sc_data && sc_data[SC_POEMBRAGI].timer!=-1) time=time*(100-(sc_data[SC_POEMBRAGI].val1*3+sc_data[SC_POEMBRAGI].val2 - +(sc_data[SC_POEMBRAGI].val3>>16)))/100; + +(sc_data[SC_POEMBRAGI].val3>>16)))/100; return (time>0)?time:0; } @@ -7172,23 +6830,48 @@ int skill_castfix( struct block_list *bl, int time ) int skill_delayfix( struct block_list *bl, int time ) { struct status_change *sc_data; + struct map_session_data *sd = NULL; + int skill = 0,lv = 0; + int delayrate = 100; nullpo_retr(0, bl); - sc_data = battle_get_sc_data(bl); - if(time<=0) - return 0; + if(bl->type == BL_PC){ + nullpo_retr(0, sd = (struct map_session_data*)bl); + skill = sd->skillid; + lv = sd->skilllv; + } - if(bl->type == BL_PC) { - if( battle_config.delay_dependon_dex ) /* dex‚̉e‹¿‚ðŒvŽZ‚·‚é */ - time=time*(battle_config.castrate_dex_scale - battle_get_dex(bl))/battle_config.castrate_dex_scale; - time=time*battle_config.delay_rate/100; + if(lv <= 0) return 0; + + sc_data = status_get_sc_data(bl); + + if(sd) { + delayrate = sd->delayrate; + + // instant cast attack skills depend on aspd as delay [celest] + if (time == 0) { + if (skill_db[skill].skill_type == BF_WEAPON) + time = status_get_adelay (bl)/2; + else + time = 300; // default delay, according to official servers + } else if (time < 0) + time = abs(time) + status_get_adelay (bl)/2; // if set to <0, the aspd delay will be added + + if(battle_config.delay_dependon_dex && /* dex‚̉e‹¿‚ðŒvŽZ‚·‚é */ + !skill_get_delaynodex(skill, lv)) // if skill casttime is allowed to be reduced by dex + time = time * (battle_config.castrate_dex_scale - status_get_dex(bl)) / (battle_config.castrate_dex_scale); + + time = time * delayrate * battle_config.delay_rate / 10000; + + if (time < battle_config.min_skill_delay_limit) // check minimum skill delay + time = battle_config.min_skill_delay_limit; } /* ƒuƒ‰ƒM‚ÌŽ */ - if(sc_data && sc_data[SC_POEMBRAGI].timer!=-1 ) - time=time*(100-(sc_data[SC_POEMBRAGI].val1*3+sc_data[SC_POEMBRAGI].val2 - +(sc_data[SC_POEMBRAGI].val3&0xffff)))/100; + if(sc_data && sc_data[SC_POEMBRAGI].timer != -1 ) + time = time * (100 - (sc_data[SC_POEMBRAGI].val1 * 3 + sc_data[SC_POEMBRAGI].val2 + + (sc_data[SC_POEMBRAGI].val3 & 0xffff))) / 100; return (time>0)?time:0; } @@ -7197,128 +6880,97 @@ int skill_delayfix( struct block_list *bl, int time ) * ƒXƒLƒ‹Žg—piIDŽw’èj *------------------------------------------ */ -int skill_use_id( struct map_session_data *sd, int target_id, - int skill_num, int skill_lv) +int skill_use_id (struct map_session_data *sd, int target_id, int skill_num, int skill_lv) { - unsigned int tick; - int casttime=0,delay=0,skill,range; - struct map_session_data* target_sd=NULL; - int forcecast=0; - struct block_list *bl; + int casttime = 0, delay = 0, skill, range; + struct map_session_data* tsd = NULL; + struct block_list *bl = NULL; struct status_change *sc_data; - tick=gettick(); + int forcecast = 0; + unsigned int tick = gettick(); nullpo_retr(0, sd); - if( (bl=map_id2bl(target_id)) == NULL ){ -/* if(battle_config.error_log) - printf("skill target not found %d\n",target_id); */ + if ((bl = map_id2bl(target_id)) == NULL) return 0; + if (bl->type == BL_PC) { + nullpo_retr(0, tsd = (struct map_session_data*)bl); } if(sd->bl.m != bl->m || pc_isdead(sd)) return 0; - if(skillnotok(skill_num, sd)) // [MouseJstr] return 0; - - sc_data=sd->sc_data; + if (tsd && skill_num == ALL_RESURRECTION && !pc_isdead(tsd)) + return 0; + + sc_data = sd->sc_data; /* ’¾?‚âˆÙíi‚½‚¾‚µAƒOƒŠƒ€‚Ȃǂ̔»’è‚ð‚·‚éj */ - if( sd->opt1>0 ) + if (sd->opt1 > 0) return 0; - if(sd->sc_data){ - if(sc_data[SC_CHASEWALK].timer != -1) return 0; - if(sc_data[SC_VOLCANO].timer != -1){ - if(skill_num==WZ_ICEWALL) return 0; - } - if(sc_data[SC_ROKISWEIL].timer!=-1){ - if(skill_num==BD_ADAPTATION) return 0; - } - if( sd->sc_data[SC_DIVINA].timer!=-1 || - sd->sc_data[SC_ROKISWEIL].timer!=-1 || - (sd->sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) || - sd->sc_data[SC_STEELBODY].timer != -1 || - sd->sc_data[SC_BERSERK].timer != -1 || - (sd->sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE)){ + if (sc_data) { + // allow to use only Chasewalk [celest] + if (sc_data[SC_CHASEWALK].timer != -1 && skill_num != ST_CHASEWALK) + return 0; + if (sc_data[SC_VOLCANO].timer != -1 && skill_num == WZ_ICEWALL) + return 0; + if (sc_data[SC_ROKISWEIL].timer != -1 && skill_num == BD_ADAPTATION) + return 0; + if (sc_data[SC_DIVINA].timer != -1 || + sc_data[SC_ROKISWEIL].timer != -1 || + (sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) || + sc_data[SC_STEELBODY].timer != -1 || + sc_data[SC_BERSERK].timer != -1 || + (sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE)) return 0; /* ?‘ÔˆÙí‚â’¾?‚È‚Ç */ + if (sc_data[SC_BLADESTOP].timer != -1) { + if (sc_data[SC_BLADESTOP].val2 == 1) return 0;//”’‰H‚³‚ꂽ‘¤‚Ȃ̂Ń_ƒ + switch (sc_data[SC_BLADESTOP].val1) { + case 1: return 0; + case 2: if (skill_num != MO_FINGEROFFENSIVE) return 0; else break; + case 3: if (skill_num != MO_FINGEROFFENSIVE && skill_num != MO_INVESTIGATE) return 0; else break; + case 4: if (skill_num != MO_FINGEROFFENSIVE && skill_num != MO_INVESTIGATE && skill_num != MO_CHAINCOMBO) return 0; else break; + case 5: if (skill_num != MO_FINGEROFFENSIVE && skill_num != MO_INVESTIGATE && skill_num != MO_CHAINCOMBO && skill_num!=MO_EXTREMITYFIST) return 0; else break; + } } - - if(sc_data[SC_BLADESTOP].timer != -1){ - int lv = sc_data[SC_BLADESTOP].val1; - if(sc_data[SC_BLADESTOP].val2==1) return 0;//”’‰H‚³‚ꂽ‘¤‚Ȃ̂Ń_ƒ - if(lv==1) return 0; - if(lv==2 && skill_num!=MO_FINGEROFFENSIVE) return 0; - if(lv==3 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE) return 0; - if(lv==4 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE && skill_num!=MO_CHAINCOMBO) return 0; - if(lv==5 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE && skill_num!=MO_CHAINCOMBO && skill_num!=MO_EXTREMITYFIST) return 0; - } - - if (sd->sc_data[SC_BLOCKSKILL].timer!=-1) - if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3) - return 0; - if (sc_data[SC_BASILICA].timer != -1) { // Disallow all other skills in Basilica [celest] - struct skill_unit *su; - if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) { - struct skill_unit_group *sg; - // if caster is the owner of basilica - if ((sg = su->group) && sg->src_id == sd->bl.id) { - // skill_status_change_end(&sd->bl,SC_BASILICA,-1); - // skill_delunitgroup (sg); - if (skill_num != HP_BASILICA) return 0; - } // otherwise... - else - return 0; - } - } + struct skill_unit_group *sg = (struct skill_unit_group *)sc_data[SC_BASILICA].val4; + // if caster is the owner of basilica + if (sg && sg->src_id == sd->bl.id && + skill_num == HP_BASILICA) ; // do nothing + // otherwise... + else return 0; + } + /* ‰‰‘t/ƒ_ƒ“ƒX’† */ + if (sc_data[SC_DANCING].timer != -1) { + if (sc_data[SC_DANCING].val4 && skill_num != BD_ADAPTATION) //‡‘t’†‚̓AƒhƒŠƒuˆÈŠO•s‰Â + return 0; + if (skill_num != BD_ADAPTATION && skill_num != BA_MUSICALSTRIKE && skill_num != DC_THROWARROW) + return 0; + } } - if(sd->status.option&4 && skill_num==TF_HIDING) + if (sd->status.option & 4 && skill_num == TF_HIDING) return 0; - if(sd->status.option&2 && skill_num!=TF_HIDING && skill_num!=AS_GRIMTOOTH && skill_num!=RG_BACKSTAP && skill_num!=RG_RAID ) + if (sd->status.option & 2 && skill_num != TF_HIDING && skill_num != AS_GRIMTOOTH && skill_num != RG_BACKSTAP && skill_num != RG_RAID) return 0; - - /*if(map[sd->bl.m].flag.gvg){ //GvG‚ÅŽg—p‚Å‚«‚È‚¢ƒXƒLƒ‹ - switch(skill_num){ - case SM_ENDURE: - case AL_TELEPORT: - case AL_WARP: - case WZ_ICEWALL: - case TF_BACKSLIDING: - //case LK_BERSERK: // now usable in WoE - celest - case HP_BASILICA: - case HP_ASSUMPTIO: - case ST_CHASEWALK: + if(skill_get_inf2(skill_num) & 0x200 && sd->bl.id == target_id) return 0; - } - }*/ - /* ‰‰‘t/ƒ_ƒ“ƒX’† */ - if( sc_data && sc_data[SC_DANCING].timer!=-1 ){ -// if(battle_config.pc_skill_log) -// printf("dancing! %d\n",skill_num); - if( sc_data[SC_DANCING].val4 && skill_num!=BD_ADAPTATION ) //‡‘t’†‚̓AƒhƒŠƒuˆÈŠO•s‰Â - return 0; - if(skill_num!=BD_ADAPTATION && skill_num!=BA_MUSICALSTRIKE && skill_num!=DC_THROWARROW){ - return 0; - } - } - - if(skill_get_inf2(skill_num)&0x200 && sd->bl.id == target_id) - return 0; //’¼‘O‚̃XƒLƒ‹‚ª‰½‚©?‚¦‚é•K—v‚Ì‚ ‚éƒXƒLƒ‹ - switch(skill_num){ + switch (skill_num) { case SA_CASTCANCEL: - if(sd->skillid != skill_num){ //ƒLƒƒƒXƒgƒLƒƒƒ“ƒZƒ‹Ž©?‚Í?‚¦‚È‚¢ + if (sd->skillid != skill_num){ //ƒLƒƒƒXƒgƒLƒƒƒ“ƒZƒ‹Ž©?‚Í?‚¦‚È‚¢ sd->skillid_old = sd->skillid; sd->skilllv_old = sd->skilllv; break; } + case BD_ENCORE: /* ƒAƒ“ƒR?ƒ‹ */ - if(!sd->skillid_dance){ //‘O‰ñŽg—p‚µ‚½—x‚肪‚È‚¢‚Æ‚¾‚ß + if (!sd->skillid_dance) { //‘O‰ñŽg—p‚µ‚½—x‚肪‚È‚¢‚Æ‚¾‚ß clif_skill_fail(sd,skill_num,0,0); return 0; - }else{ + } else { sd->skillid_old = skill_num; } break; @@ -7331,19 +6983,15 @@ int skill_use_id( struct map_session_data *sd, int target_id, struct guild *g; if (!sd->status.guild_id) return 0; - if (!(g = guild_search(sd->status.guild_id))) + if ((g = guild_search(sd->status.guild_id)) == NULL) return 0; if (strcmp(sd->status.name,g->master)) return 0; - if (skill_lv <= 0) skill_lv = 1; + skill_lv = guild_checkskill(g, skill_num); + if (skill_lv <= 0) return 0; } break; - } - - sd->skillid = skill_num; - sd->skilllv = skill_lv; - switch(skill_num){ //Ž–‘O‚ɃŒƒxƒ‹‚ª?‚í‚Á‚½‚è‚·‚éƒXƒLƒ‹ case BD_LULLABY: /* ŽqŽç‰Ì */ case BD_RICHMANKIM: /* ƒjƒˆƒ‹ƒh‚̉ƒ */ case BD_ETERNALCHAOS: /* ‰i‰“‚̬“× */ @@ -7355,120 +7003,179 @@ int skill_use_id( struct map_session_data *sd, int target_id, case BD_RAGNAROK: /* _?‚Ì?¨ */ case CG_MOONLIT: /* ŒŽ–¾‚è‚Ìò‚É—Ž‚¿‚é‰Ô‚Ñ‚ç */ { - int range=1; - int c=0; - map_foreachinarea(skill_check_condition_char_sub,sd->bl.m, - sd->bl.x-range,sd->bl.y-range, - sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c); - if(c<1){ + int range = 1; + int c = 0; + map_foreachinarea (skill_check_condition_char_sub, sd->bl.m, + sd->bl.x-range, sd->bl.y-range, + sd->bl.x+range, sd->bl.y+range, BL_PC, &sd->bl, &c); + if (c < 1) { clif_skill_fail(sd,skill_num,0,0); return 0; - }else if(c==99){ //‘Š•û•s—vݒ肾‚Á‚½ + } else if (c == 99) { //‘Š•û•s—vݒ肾‚Á‚½ ; - }else{ - sd->skilllv=(c + skill_lv)/2; + } else { + sd->skilllv = (c + skill_lv)/2; } } break; } - if(!skill_check_condition(sd,0)) return 0; - - /* ŽË’ö‚ÆáŠQ•¨ƒ`ƒFƒbƒN */ - range = skill_get_range(skill_num,skill_lv); - if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); - if(!battle_check_range(&sd->bl,bl,range) ) - return 0; + sd->skillid = skill_num; + sd->skilllv = skill_lv; + if (!skill_check_condition(sd,0)) return 0; - if(bl->type==BL_PC) { - target_sd=(struct map_session_data*)bl; - if(target_sd && skill_num == ALL_RESURRECTION && !pc_isdead(target_sd)) - return 0; + { + int check_range_flag = 0; + + /* ŽË’ö‚ÆáŠQ•¨ƒ`ƒFƒbƒN */ + range = skill_get_range(skill_num,skill_lv); + if(range < 0) + range = status_get_range(&sd->bl) - (range + 1); + // be lenient if the skill was cast before we have moved to the correct position [Celest] + if (sd->walktimer != -1) + range++; + else check_range_flag = 1; + if(!battle_check_range(&sd->bl,bl,range)) { + if (check_range_flag && battle_check_range(&sd->bl,bl,range + 1)) { + int mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}}; + int dir = map_calc_dir(&sd->bl,bl->x,bl->y); + pc_walktoxy (sd, sd->bl.x + mask[dir][0], sd->bl.y + mask[dir][1]); + } else + return 0; + } } - if((skill_num != MO_CHAINCOMBO && - skill_num != MO_COMBOFINISH && - skill_num != MO_EXTREMITYFIST && - skill_num != CH_TIGERFIST && - skill_num != CH_CHAINCRUSH) || + + if ((skill_num != MO_CHAINCOMBO && + skill_num != MO_COMBOFINISH && + skill_num != MO_EXTREMITYFIST && + skill_num != CH_TIGERFIST && + skill_num != CH_CHAINCRUSH) || + (skill_num == CH_CHAINCRUSH && sd->state.skill_flag) || (skill_num == MO_EXTREMITYFIST && sd->state.skill_flag) ) pc_stopattack(sd); - casttime=skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) ); - if(skill_num != SA_MAGICROD) - delay=skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) ); - //sd->state.skillcastcancel = skill_db[skill_num].castcancel; + casttime = skill_castfix(&sd->bl, skill_get_cast(skill_num, skill_lv)); + if (skill_num != SA_MAGICROD) + delay = skill_delayfix(&sd->bl, skill_get_delay(skill_num, skill_lv)); sd->state.skillcastcancel = skill_get_castcancel(skill_num); - switch(skill_num){ /* ‰½‚©“ÁŽê‚È?—‚ª•K—v */ -// case AL_HEAL: /* ƒq?ƒ‹ */ -// if(battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) -// forcecast=1; /* ƒq?ƒ‹ƒAƒ^ƒbƒN‚È‚ç‰r¥ƒGƒtƒFƒNƒg—L‚è */ -// break; + switch (skill_num) { /* ‰½‚©“ÁŽê‚È?—‚ª•K—v */ case ALL_RESURRECTION: /* ƒŠƒUƒŒƒNƒVƒ‡ƒ“ */ - if(bl->type != BL_PC && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))){ /* “G‚ªƒAƒ“ƒfƒbƒh‚È‚ç */ - forcecast=1; /* ƒ^?ƒ“ƒAƒ“ƒfƒbƒg‚Æ“¯‚¶‰r¥ŽžŠÔ */ - casttime=skill_castfix(&sd->bl, skill_get_cast(PR_TURNUNDEAD,skill_lv) ); + if (!tsd && battle_check_undead(status_get_race(bl),status_get_elem_type(bl))) { /* “G‚ªƒAƒ“ƒfƒbƒh‚È‚ç */ + forcecast = 1; /* ƒ^?ƒ“ƒAƒ“ƒfƒbƒg‚Æ“¯‚¶‰r¥ŽžŠÔ */ + casttime = skill_castfix(&sd->bl, skill_get_cast(PR_TURNUNDEAD, skill_lv)); } break; + case MO_FINGEROFFENSIVE: /* Žw? */ - casttime += casttime * ((skill_lv > sd->spiritball)? sd->spiritball:skill_lv); + casttime += casttime * ((skill_lv > sd->spiritball) ? sd->spiritball : skill_lv); break; + case MO_CHAINCOMBO: /*˜A‘Ŷ*/ target_id = sd->attacktarget; - if( sc_data && sc_data[SC_BLADESTOP].timer!=-1 ){ + if (sc_data && sc_data[SC_BLADESTOP].timer != -1){ struct block_list *tbl; - if((tbl=(struct block_list *)sc_data[SC_BLADESTOP].val4) == NULL) //ƒ^?ƒQƒbƒg‚ª‚¢‚È‚¢H + if ((tbl=(struct block_list *)sc_data[SC_BLADESTOP].val4) == NULL) //ƒ^?ƒQƒbƒg‚ª‚¢‚È‚¢H return 0; target_id = tbl->id; } break; - case MO_COMBOFINISH: /*–Ò—´Œ*/ - case CH_TIGERFIST: /* •šŒÕŒ */ + case MO_COMBOFINISH: /*–Ò—´Œ*/ case CH_CHAINCRUSH: /* ˜A’Œ•ö? */ target_id = sd->attacktarget; break; + case CH_TIGERFIST: /* •šŒÕŒ */ + if (sc_data && sc_data[SC_COMBO].timer != -1 && sc_data[SC_COMBO].val1 == MO_COMBOFINISH) + target_id = sd->attacktarget; + break; + // -- moonsoul (altered to allow proper usage of extremity from new champion combos) // case MO_EXTREMITYFIST: /*ˆ¢C—…”e–PŒ*/ - if(sc_data && sc_data[SC_COMBO].timer != -1 && (sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) { + if (sc_data && sc_data[SC_COMBO].timer != -1 && (sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) { casttime = 0; target_id = sd->attacktarget; } - forcecast=1; + forcecast = 1; break; + case SA_MAGICROD: case SA_SPELLBREAKER: - forcecast=1; + forcecast = 1; break; + case WE_MALE: case WE_FEMALE: { - struct map_session_data *p_sd = NULL; - if((p_sd = pc_get_partner(sd)) == NULL) + struct map_session_data *p_sd = pc_get_partner(sd); + if (p_sd == NULL) + return 0; + if (skill_num == WE_MALE && sd->status.hp <= ((15*sd->status.max_hp)/100)) // Requires more than 15% of Max HP for WE_MALE + return 0; + else if (skill_num == WE_FEMALE && sd->status.sp <= ((15*sd->status.max_sp)/100)) // Requires more than 15% of Max SP for WE_FEMALE return 0; target_id = p_sd->bl.id; //range‚ð‚à‚¤1‰ñ?¸ - range = skill_get_range(skill_num,skill_lv); - if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); - if(!battle_check_range(&sd->bl,&p_sd->bl,range)) + if (!battle_check_range(&sd->bl, &p_sd->bl, skill_get_range(skill_num,skill_lv))) return 0; } break; - case AS_SPLASHER: /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ? */ + + // parent-baby skills + case WE_BABY: + case WE_CALLPARENT: + { + struct map_session_data *f_sd = pc_get_father(sd); + struct map_session_data *m_sd = pc_get_mother(sd); + + // set target as any one of the parent + if (f_sd) target_id = f_sd->bl.id; + else if (m_sd) target_id = m_sd->bl.id; + else return 0; // neither are found + + // skip range check + //range‚ð‚à‚¤1‰ñ?¸ + //range = skill_get_range(skill_num,skill_lv); + //if(!battle_check_range(&sd->bl,&p_sd->bl,range)) + // return 0; + } + break; + + case WE_CALLBABY: { - struct status_change *t_sc_data = battle_get_sc_data(bl); - if(t_sc_data && t_sc_data[SC_POISON].timer==-1){ - clif_skill_fail(sd,skill_num,0,10); + struct map_session_data *p_sd = pc_get_child(sd); + if (p_sd == NULL) + return 0; + target_id = p_sd->bl.id; + //range‚ð‚à‚¤1‰ñ?¸ + if(!battle_check_range(&sd->bl, &p_sd->bl, skill_get_range(skill_num,skill_lv))) return 0; - } } break; - case PF_MEMORIZE: /* ƒƒ‚ƒ‰ƒCƒY */ - casttime = 12000; + + case HP_BASILICA: /* ƒoƒWƒŠƒJ */ + { + if (skill_check_unit_range(sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) { + clif_skill_fail(sd,sd->skillid,0,0); + return 0; + } + if (skill_check_unit_range2(&sd->bl,sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) { + clif_skill_fail(sd,sd->skillid,0,0); + return 0; + } + // cancel Basilica if already in effect + if (sc_data && sc_data[SC_BASILICA].timer != -1) { + struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc_data[SC_BASILICA].val4; + if (sg && sg->src_id == sd->bl.id) { + status_change_end(&sd->bl,SC_BASILICA,-1); + skill_delunitgroup (sg); + return 0; + } + } + } break; + case GD_BATTLEORDER: case GD_REGENERATION: case GD_RESTORE: @@ -7478,62 +7185,52 @@ int skill_use_id( struct map_session_data *sd, int target_id, } //ƒƒ‚ƒ‰ƒCƒY?‘Ô‚È‚çƒLƒƒƒXƒgƒ^ƒCƒ€‚ª1/3 - if(sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){ + if (sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0) { casttime = casttime/2; - if((--sc_data[SC_MEMORIZE].val2)<=0) - skill_status_change_end(&sd->bl, SC_MEMORIZE, -1); + if ((--sc_data[SC_MEMORIZE].val2) <= 0) + status_change_end(&sd->bl, SC_MEMORIZE, -1); } - if(battle_config.pc_skill_log) - printf("PC %d skill use target_id=%d skill=%d lv=%d cast=%d\n",sd->bl.id,target_id,skill_num,skill_lv,casttime); + if (battle_config.pc_skill_log) + printf ("PC %d skill use target_id=%d skill=%d lv=%d cast=%d\n", + sd->bl.id, target_id, skill_num, skill_lv, casttime); -// if(sd->skillitem == skill_num) -// casttime = delay = 0; - - if( casttime>0 || forcecast ){ /* ‰r¥‚ª•K—v */ + if (casttime > 0 || forcecast) { /* ‰r¥‚ª•K—v */ struct mob_data *md; - clif_skillcasting( &sd->bl, sd->bl.id, target_id, 0,0, skill_num,casttime); + clif_skillcasting(&sd->bl, sd->bl.id, target_id, 0,0, skill_num,casttime); /* ‰r¥”½?ƒ‚ƒ“ƒXƒ^? */ - if( bl->type==BL_MOB && (md=(struct mob_data *)bl) && mob_db[md->class].mode&0x10 && - md->state.state!=MS_ATTACK && sd->invincible_timer == -1){ - md->target_id=sd->bl.id; + if (bl->type == BL_MOB && (md = (struct mob_data *)bl) && mob_db[md->class_].mode & 0x10 && + md->state.state != MS_ATTACK && sd->invincible_timer == -1){ + md->target_id = sd->bl.id; md->state.targettype = ATTACKABLE; - md->min_chase=13; + md->min_chase = 13; } } - if( casttime<=0 ) /* ‰r¥‚Ì–³‚¢‚à‚̂̓Lƒƒƒ“ƒZƒ‹‚³‚ê‚È‚¢ */ - sd->state.skillcastcancel=0; - - sd->skilltarget = target_id; -/* sd->cast_target_bl = bl; */ - sd->skillx = 0; - sd->skilly = 0; + sd->skilltarget = target_id; + sd->skillx = 0; + sd->skilly = 0; sd->canact_tick = tick + casttime + delay; sd->canmove_tick = tick; - if(!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1 && sd->skillid != AS_CLOAKING) - skill_status_change_end(&sd->bl,SC_CLOAKING,-1); - if(casttime > 0) { - sd->skilltimer = add_timer( tick+casttime, skill_castend_id, sd->bl.id, 0 ); - if((skill = pc_checkskill(sd,SA_FREECAST)) > 0) { + + if (!(battle_config.pc_cloak_check_type & 2) && sc_data && sc_data[SC_CLOAKING].timer != -1 && sd->skillid != AS_CLOAKING) + status_change_end(&sd->bl,SC_CLOAKING,-1); + if (casttime > 0) { + sd->skilltimer = add_timer (tick + casttime, skill_castend_id, sd->bl.id, 0); + if ((skill = pc_checkskill(sd,SA_FREECAST)) > 0) { sd->prev_speed = sd->speed; - sd->speed = sd->speed*(175 - skill*5)/100; - clif_updatestatus(sd,SP_SPEED); + status_calc_speed (sd); } else pc_stop_walking(sd,0); - } - else { - if(skill_num != SA_CASTCANCEL) + } else { + sd->state.skillcastcancel = 0; /* ‰r¥‚Ì–³‚¢‚à‚̂̓Lƒƒƒ“ƒZƒ‹‚³‚ê‚È‚¢ */ + if (skill_num != SA_CASTCANCEL) sd->skilltimer = -1; skill_castend_id(sd->skilltimer,tick,sd->bl.id,0); } - //ƒ}ƒWƒbƒNƒpƒ?‚Ì?‰ÊI—¹ - //if(sc_data && sc_data[SC_MAGICPOWER].timer != -1 && skill_num != HW_MAGICPOWER) - // skill_status_change_end(&sd->bl,SC_MAGICPOWER,-1); // moved - return 0; } @@ -7541,137 +7238,127 @@ int skill_use_id( struct map_session_data *sd, int target_id, * ƒXƒLƒ‹Žg—piꊎw’èj *------------------------------------------ */ -int skill_use_pos( struct map_session_data *sd, - int skill_x, int skill_y, int skill_num, int skill_lv) +int skill_use_pos (struct map_session_data *sd, int skill_x, int skill_y, int skill_num, int skill_lv) { struct block_list bl; struct status_change *sc_data; - unsigned int tick; - int casttime=0,delay=0,skill,range; + int casttime = 0, delay = 0, skill, range; + unsigned int tick = gettick(); nullpo_retr(0, sd); - if(pc_isdead(sd)) + if (pc_isdead(sd)) return 0; - if (skillnotok(skill_num, sd)) // [MoueJstr] return 0; - - if(skill_num==WZ_ICEWALL && map[sd->bl.m].flag.noicewall && !map[sd->bl.m].flag.pvp) { // noicewall flag [Valaris] + if (skill_num == WZ_ICEWALL && map[sd->bl.m].flag.noicewall && !map[sd->bl.m].flag.pvp) { // noicewall flag [Valaris] clif_skill_fail(sd,sd->skillid,0,0); return 0; } - sc_data=sd->sc_data; + sc_data = sd->sc_data; - if( sd->opt1>0 ) + if (sd->opt1 > 0) return 0; - if(sc_data){ - if( sc_data[SC_DIVINA].timer!=-1 || - sc_data[SC_ROKISWEIL].timer!=-1 || + if (sc_data){ + if (sc_data[SC_DIVINA].timer != -1 || + sc_data[SC_ROKISWEIL].timer != -1 || sc_data[SC_AUTOCOUNTER].timer != -1 || sc_data[SC_STEELBODY].timer != -1 || sc_data[SC_DANCING].timer!=-1 || sc_data[SC_BERSERK].timer != -1 || - sd->sc_data[SC_MARIONETTE].timer != -1) + sc_data[SC_MARIONETTE].timer != -1) return 0; /* ?‘ÔˆÙí‚â’¾?‚È‚Ç */ - if (sd->sc_data[SC_BLOCKSKILL].timer!=-1) - if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3) - return 0; - - if (sc_data[SC_BASILICA].timer != -1) { // Basilica cancels if caster moves [celest] - struct skill_unit *su; - if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) { - struct skill_unit_group *sg; - // if caster is the owner of basilica - if ((sg = su->group) && sg->src_id == sd->bl.id) { - // skill_status_change_end(&sd->bl,SC_BASILICA,-1); - // skill_delunitgroup (sg); - if (skill_num != HP_BASILICA) return 0; - } // otherwise... - else - return 0; - } + if (sc_data[SC_BASILICA].timer != -1) { + struct skill_unit_group *sg = (struct skill_unit_group *)sc_data[SC_BASILICA].val4; + // if caster is the owner of basilica + if (sg && sg->src_id == sd->bl.id && + skill_num == HP_BASILICA) ; // do nothing + // otherwise... + else return 0; } } - if(sd->status.option&2) + if(sd->status.option & 2) return 0; -/* if(map[sd->bl.m].flag.gvg && - (skill_num == SM_ENDURE || skill_num == AL_TELEPORT || - skill_num == AL_WARP || skill_num == WZ_ICEWALL || - skill_num == TF_BACKSLIDING)) - return 0;*/ - sd->skillid = skill_num; sd->skilllv = skill_lv; - if(skill_lv <= 0) return 0; + if (skill_lv <= 0) return 0; sd->skillx = skill_x; sd->skilly = skill_y; - if(!skill_check_condition(sd,0)) return 0; + if (!skill_check_condition(sd,0)) return 0; /* ŽË’ö‚ÆáŠQ•¨ƒ`ƒFƒbƒN */ bl.type = BL_NUL; bl.m = sd->bl.m; bl.x = skill_x; bl.y = skill_y; - range = skill_get_range(skill_num,skill_lv); - if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); - if(!battle_check_range(&sd->bl,&bl,range) ) - return 0; + + { + int check_range_flag = 0; + + /* ŽË’ö‚ÆáŠQ•¨ƒ`ƒFƒbƒN */ + range = skill_get_range(skill_num,skill_lv); + if(range < 0) + range = status_get_range(&sd->bl) - (range + 1); + // be lenient if the skill was cast before we have moved to the correct position [Celest] + if (sd->walktimer != -1) + range ++; + else check_range_flag = 1; + if(!battle_check_range(&sd->bl,&bl,range)) { + if (check_range_flag && battle_check_range(&sd->bl,&bl,range + 1)) { + int mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}}; + int dir = map_calc_dir(&sd->bl,bl.x,bl.y); + pc_walktoxy (sd, sd->bl.x + mask[dir][0], sd->bl.y + mask[dir][1]); + } else + return 0; + } + } pc_stopattack(sd); - casttime=skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) ); - delay=skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) ); + casttime = skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) ); + delay = skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) ); sd->state.skillcastcancel = skill_db[skill_num].castcancel; - if(battle_config.pc_skill_log) - printf("PC %d skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d\n",sd->bl.id,skill_x,skill_y,skill_num,skill_lv,casttime); + if (battle_config.pc_skill_log) + printf("PC %d skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d\n", + sd->bl.id, skill_x, skill_y, skill_num, skill_lv, casttime); -// if(sd->skillitem == skill_num) -// casttime = delay = 0; //ƒƒ‚ƒ‰ƒCƒY?‘Ô‚È‚çƒLƒƒƒXƒgƒ^ƒCƒ€‚ª1/3 - if(sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){ + if (sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){ casttime = casttime/3; - if((--sc_data[SC_MEMORIZE].val2)<=0) - skill_status_change_end(&sd->bl, SC_MEMORIZE, -1); + if ((--sc_data[SC_MEMORIZE].val2)<=0) + status_change_end(&sd->bl, SC_MEMORIZE, -1); } - if( casttime>0 ) /* ‰r¥‚ª•K—v */ - clif_skillcasting( &sd->bl, - sd->bl.id, 0, skill_x,skill_y, skill_num,casttime); - - if( casttime<=0 ) /* ‰r¥‚Ì–³‚¢‚à‚̂̓Lƒƒƒ“ƒZƒ‹‚³‚ê‚È‚¢ */ - sd->state.skillcastcancel=0; - + if (casttime > 0) /* ‰r¥‚ª•K—v */ + clif_skillcasting(&sd->bl, sd->bl.id, 0, skill_x, skill_y, skill_num, casttime); + sd->skilltarget = 0; -/* sd->cast_target_bl = NULL; */ - tick=gettick(); sd->canact_tick = tick + casttime + delay; sd->canmove_tick = tick; - if(!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1) - skill_status_change_end(&sd->bl,SC_CLOAKING,-1); - if(casttime > 0) { - sd->skilltimer = add_timer( tick+casttime, skill_castend_pos, sd->bl.id, 0 ); - if((skill = pc_checkskill(sd,SA_FREECAST)) > 0) { + if (!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1) + status_change_end(&sd->bl,SC_CLOAKING,-1); + if (casttime > 0) { + sd->skilltimer = add_timer(tick + casttime, skill_castend_pos, sd->bl.id, 0); + if ((skill = pc_checkskill(sd,SA_FREECAST)) > 0) { sd->prev_speed = sd->speed; - sd->speed = sd->speed*(175 - skill*5)/100; - clif_updatestatus(sd,SP_SPEED); + status_calc_speed (sd); } else pc_stop_walking(sd,0); - } - else { + } else { + sd->state.skillcastcancel = 0; /* ‰r¥‚Ì–³‚¢‚à‚̂̓Lƒƒƒ“ƒZƒ‹‚³‚ê‚È‚¢ */ sd->skilltimer = -1; skill_castend_pos(sd->skilltimer,tick,sd->bl.id,0); } //ƒ}ƒWƒbƒNƒpƒ?‚Ì?‰ÊI—¹ - if(sc_data && sc_data[SC_MAGICPOWER].timer != -1 && skill_num != HW_MAGICPOWER) - skill_status_change_end(&sd->bl,SC_MAGICPOWER,-1); + if (skill_get_unit_id(skill_num, 0) != 0x86 && + sc_data && sc_data[SC_MAGICPOWER].timer != -1) + status_change_end(&sd->bl,SC_MAGICPOWER,-1); return 0; } @@ -7680,60 +7367,59 @@ int skill_use_pos( struct map_session_data *sd, * ƒXƒLƒ‹‰r¥ƒLƒƒƒ“ƒZƒ‹ *------------------------------------------ */ -int skill_castcancel(struct block_list *bl,int type) +int skill_castcancel (struct block_list *bl, int type) { int inf; - int ret=0; + int ret = 0; nullpo_retr(0, bl); - if(bl->type==BL_PC){ - struct map_session_data *sd=(struct map_session_data *)bl; - unsigned long tick=gettick(); + if (bl->type == BL_PC) { + struct map_session_data *sd = (struct map_session_data *)bl; + unsigned long tick = gettick(); nullpo_retr(0, sd); - sd->canact_tick=tick; + sd->canact_tick = tick; sd->canmove_tick = tick; - if( sd->skilltimer!=-1){ - if(pc_checkskill(sd,SA_FREECAST) > 0) { + if (sd->skilltimer != -1) { + if (pc_checkskill(sd,SA_FREECAST) > 0) { sd->speed = sd->prev_speed; clif_updatestatus(sd,SP_SPEED); } - if(!type) { - if((inf = skill_get_inf( sd->skillid )) == 2 || inf == 32) - ret=delete_timer( sd->skilltimer, skill_castend_pos ); + if (!type) { + if ((inf = skill_get_inf( sd->skillid )) == 2 || inf == 32) + ret = delete_timer( sd->skilltimer, skill_castend_pos ); else ret=delete_timer( sd->skilltimer, skill_castend_id ); - if(ret<0) - printf("delete timer error : skillid : %d\n",sd->skillid); - } - else { - if((inf = skill_get_inf( sd->skillid_old )) == 2 || inf == 32) - ret=delete_timer( sd->skilltimer, skill_castend_pos ); + if (ret < 0) + printf("delete timer error : skillid : %d\n", sd->skillid); + } else { + if ((inf = skill_get_inf( sd->skillid_old )) == 2 || inf == 32) + ret = delete_timer( sd->skilltimer, skill_castend_pos ); else - ret=delete_timer( sd->skilltimer, skill_castend_id ); - if(ret<0) - printf("delete timer error : skillid : %d\n",sd->skillid_old); + ret = delete_timer( sd->skilltimer, skill_castend_id ); + if (ret < 0) + printf("delete timer error : skillid : %d\n", sd->skillid_old); } - sd->skilltimer=-1; + sd->skilltimer = -1; clif_skillcastcancel(bl); } - return 0; - }else if(bl->type==BL_MOB){ - struct mob_data *md=(struct mob_data *)bl; + } else if (bl->type == BL_MOB) { + struct mob_data *md = (struct mob_data *)bl; nullpo_retr(0, md); - if( md->skilltimer!=-1 ){ - if((inf = skill_get_inf( md->skillid )) == 2 || inf == 32) - ret=delete_timer( md->skilltimer, mobskill_castend_pos ); + if (md->skilltimer != -1) { + if ((inf = skill_get_inf( md->skillid )) == 2 || inf == 32) + ret = delete_timer( md->skilltimer, mobskill_castend_pos ); else - ret=delete_timer( md->skilltimer, mobskill_castend_id ); - md->skilltimer=-1; + ret = delete_timer( md->skilltimer, mobskill_castend_id ); + md->skilltimer = -1; clif_skillcastcancel(bl); } - if(ret<0) - printf("delete timer error : skillid : %d\n",md->skillid); + if (ret < 0) + printf("delete timer error : skillid : %d\n", md->skillid); return 0; } + return 1; } /*========================================= @@ -7912,13 +7598,14 @@ int skill_devotion3(struct block_list *bl,int target) int n,r=0; nullpo_retr(1, bl); + md = (struct map_session_data *)bl; - if( (md = (struct map_session_data *)bl) == NULL || (sd = map_id2sd(target)) == NULL ) + if ((sd = map_id2sd(target))==NULL) return 1; else r = distance(bl->x,bl->y,sd->bl.x,sd->bl.y); - if(pc_checkskill(sd,CR_DEVOTION)+6 < r){ // ‹–—e”Í?‚ð’´‚¦‚Ä‚½ + if(pc_checkskill(md,CR_DEVOTION)+6 < r){ // ‹–—e”Í?‚ð’´‚¦‚Ä‚½ for(n=0;n<5;n++) if(md->dev.val1[n]==target) md->dev.val2[n]=0; // —£‚ê‚½Žž‚ÍA?‚ð؂邾‚¯ @@ -7936,7 +7623,7 @@ void skill_devotion_end(struct map_session_data *md,struct map_session_data *sd, md->dev.val1[target]=md->dev.val2[target]=0; if(sd && sd->sc_data){ - // skill_status_change_end(sd->bl,SC_DEVOTION,-1); + // status_change_end(sd->bl,SC_DEVOTION,-1); sd->sc_data[SC_DEVOTION].val1=0; sd->sc_data[SC_DEVOTION].val2=0; clif_status_change(&sd->bl,SC_DEVOTION,0); @@ -7978,7 +7665,7 @@ int skill_autospell(struct map_session_data *sd,int skillid) if(maxlv > (lv=pc_checkskill(sd,skillid))) maxlv = lv; - skill_status_change_start(&sd->bl,SC_AUTOSPELL,skilllv,skillid,maxlv,0, // val1:ƒXƒLƒ‹ID val2:Žg—pÅ‘åLv + status_change_start(&sd->bl,SC_AUTOSPELL,skilllv,skillid,maxlv,0, // val1:ƒXƒLƒ‹ID val2:Žg—pÅ‘åLv skill_get_time(SA_AUTOSPELL,skilllv),0);// ‚É‚µ‚Ă݂½‚¯‚Çbscript‚ª‘‚«ˆÕ‚¢???H return 0; } @@ -8087,34 +7774,64 @@ int skill_frostjoke_scream(struct block_list *bl,va_list ap) if(src == bl)//Ž©•ª‚É‚Í?‚©‚È‚¢ return 0; - if(battle_check_target(src,bl,BCT_ENEMY) > 0) + if (map[src->m].flag.gvg || map[src->m].flag.pvp) skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick); - else if(battle_check_target(src,bl,BCT_PARTY) > 0) { - if(rand()%100 < 10)//PTƒƒ“ƒo‚É‚à’áŠm—¦‚Å‚©‚©‚é(‚Æ‚è‚ ‚¦‚¸10%) + // we freeze everybody except of ourselfes on pvp/gvg [veider] + else { + if(battle_check_target(src,bl,BCT_ENEMY) > 0) + skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick); + else if(battle_check_target(src,bl,BCT_PARTY) > 0 && rand()%100 < 10) skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick); } + // so on non-pvp/gvg we are just freezing as freezed before return 0; } /*========================================== - *ƒAƒuƒ‰ƒJƒ_ƒuƒ‰‚ÌŽg—pƒXƒLƒ‹Œˆ’è(Œˆ’èƒXƒLƒ‹‚ªƒ_ƒ‚È‚ç0‚ð•Ô‚·) + * Moonlit creates a 'safe zone' [celest] *------------------------------------------ */ -int skill_abra_dataset(int skilllv) +static int skill_moonlit_count(struct block_list *bl,va_list ap) { - int skill = rand()%331; + int *c, id; + struct map_session_data *sd; - if(skilllv <= 0) return 0; + nullpo_retr(0, bl); + nullpo_retr(0, ap); + nullpo_retr(0, (sd=(struct map_session_data *)bl)); - //db‚ɊŒƒxƒ‹?Šm—¦”»’è - if(skill_abra_db[skill].req_lv > skilllv || rand()%10000 >= skill_abra_db[skill].per) return 0; - //NPCƒXƒLƒ‹‚̓_ƒ - if(skill >= NPC_PIERCINGATT && skill <= NPC_SUMMONMONSTER) return 0; - //‰‰‘tƒXƒLƒ‹‚̓_ƒ - if(skill_is_danceskill(skill)) return 0; + id=va_arg(ap,int); + c=va_arg(ap,int *); - return skill; + if (sd->bl.id != id && sd->sc_count && sd->sc_data[SC_MOONLIT].timer != -1 && c) + (*c)++; + return 0; +} + +int skill_check_moonlit (struct block_list *bl, int dx, int dy) +{ + int c=0; + nullpo_retr(0, bl); + map_foreachinarea(skill_moonlit_count,bl->m, + dx-1,dy-1,dx+1,dy+1,BL_PC,bl->id,&c); + return (c>0); +} + +/*========================================== + * ƒoƒWƒŠƒJ‚̃Zƒ‹‚ðÝ’è‚·‚é + *------------------------------------------ + */ +void skill_basilica_cell(struct skill_unit *unit,int flag) +{ + int i,x,y,range = skill_get_unit_range(HP_BASILICA); + int size = range*2+1; + + for (i=0;i<size*size;i++) { + x = unit->bl.x+(i%size-range); + y = unit->bl.y+(i/size-range); + map_setcell(unit->bl.m,x,y,flag); + } } /*========================================== @@ -8137,7 +7854,8 @@ int skill_attack_area(struct block_list *bl,va_list ap) return 0; skillid=va_arg(ap,int); skilllv=va_arg(ap,int); - if(skilllv <= 0) return 0; + //if(skilllv <= 0) return 0; + if(skillid > 0 && skilllv <= 0) return 0; // celest tick=va_arg(ap,unsigned int); flag=va_arg(ap,int); type=va_arg(ap,int); @@ -8155,16 +7873,20 @@ int skill_clear_element_field(struct block_list *bl) { struct mob_data *md=NULL; struct map_session_data *sd=NULL; - int i,skillid; + int i,max,skillid; nullpo_retr(0, bl); - if(bl->type==BL_MOB) - md=(struct mob_data *)bl; - if(bl->type==BL_PC) - sd=(struct map_session_data *)bl; + if (bl->type==BL_MOB) { + max = MAX_MOBSKILLUNITGROUP; + md = (struct mob_data *)bl; + } else if(bl->type==BL_PC) { + max = MAX_SKILLUNITGROUP; + sd = (struct map_session_data *)bl; + } else + return 0; - for(i=0;i<MAX_MOBSKILLUNITGROUP;i++){ + for (i=0;i<max;i++) { if(sd){ skillid=sd->skillunit[i].skill_id; if(skillid==SA_DELUGE||skillid==SA_VOLCANO||skillid==SA_VIOLENTGALE||skillid==SA_LANDPROTECTOR) @@ -8190,43 +7912,43 @@ int skill_landprotector(struct block_list *bl, va_list ap ) nullpo_retr(0, bl); nullpo_retr(0, ap); - skillid=va_arg(ap,int); - alive=va_arg(ap,int *); - if((unit=(struct skill_unit *)bl) == NULL) + skillid = va_arg(ap,int); + alive = va_arg(ap,int *); + + if ((unit = (struct skill_unit *)bl) == NULL) return 0; - if(skillid==SA_LANDPROTECTOR){ + if (skillid == SA_LANDPROTECTOR) skill_delunit(unit); - }else{ - if(alive && unit->group->skill_id==SA_LANDPROTECTOR) - (*alive)=0; - } + else if (alive && unit->group && unit->group->skill_id == SA_LANDPROTECTOR) + (*alive) = 0; + return 0; } /*========================================== * ƒCƒhƒDƒ“‚Ì—ÑŒç‚̉ñ•œ?—(foreachinarea) *------------------------------------------ */ -int skill_idun_heal(struct block_list *bl, va_list ap ) +int skill_idun_heal (struct block_list *bl, va_list ap) { struct skill_unit *unit; struct skill_unit_group *sg; int heal; nullpo_retr(0, bl); + if (bl->type != BL_PC && bl->type != BL_MOB) + return 0; + nullpo_retr(0, ap); nullpo_retr(0, unit = va_arg(ap,struct skill_unit *)); nullpo_retr(0, sg = unit->group); - - heal=30+sg->skill_lv*5+((sg->val1)>>16)*5+((sg->val1)&0xfff)/2; - - if(bl->type == BL_SKILL || bl->id == sg->src_id) + if (bl->id == sg->src_id) return 0; - if(bl->type == BL_PC || bl->type == BL_MOB){ - clif_skill_nodamage(&unit->bl,bl,AL_HEAL,heal,1); - battle_heal(NULL,bl,heal,0,0); - } + heal = 30 + sg->skill_lv * 5 + ((sg->val1) >> 16) * 5 + ((sg->val1) & 0xfff) / 2; + clif_skill_nodamage(&unit->bl, bl, AL_HEAL, heal, 1); + battle_heal(NULL, bl, heal, 0, 0); + return 0; } @@ -8234,18 +7956,19 @@ int skill_idun_heal(struct block_list *bl, va_list ap ) * Žw’è”Í??‚Åsrc‚É?‚µ‚Ä—L?‚ȃ^?ƒQƒbƒg‚Ìbl‚Ì?‚ð?‚¦‚é(foreachinarea) *------------------------------------------ */ -int skill_count_target(struct block_list *bl, va_list ap ){ +int skill_count_target (struct block_list *bl, va_list ap) +{ struct block_list *src; int *c; nullpo_retr(0, bl); nullpo_retr(0, ap); - if((src = va_arg(ap,struct block_list *)) == NULL) + if ((src = va_arg(ap,struct block_list *)) == NULL) return 0; - if((c = va_arg(ap,int *)) == NULL) + if ((c = va_arg(ap,int *)) == NULL) return 0; - if(battle_check_target(src,bl,BCT_ENEMY) > 0) + if (battle_check_target(src,bl,BCT_ENEMY) > 0) (*c)++; return 0; } @@ -8253,7 +7976,7 @@ int skill_count_target(struct block_list *bl, va_list ap ){ * ƒgƒ‰ƒbƒv”Í??—(foreachinarea) *------------------------------------------ */ -int skill_trap_splash(struct block_list *bl, va_list ap ) +int skill_trap_splash (struct block_list *bl, va_list ap) { struct block_list *src; int tick; @@ -8285,6 +8008,7 @@ int skill_trap_splash(struct block_list *bl, va_list ap ) for(i=0;i<splash_count;i++){ skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,(sg->val2)?0x0500:0); } + break; case 0x97: /* ƒtƒŠ?ƒWƒ“ƒOƒgƒ‰ƒbƒv */ skill_attack(BF_WEAPON, ss,src,bl,sg->skill_id,sg->skill_lv,tick,(sg->val2)?0x0500:0); break; @@ -8295,1720 +8019,74 @@ int skill_trap_splash(struct block_list *bl, va_list ap ) return 0; } -/*---------------------------------------------------------------------------- - * ƒXƒe?ƒ^ƒXˆÙí - *---------------------------------------------------------------------------- - */ - -/*========================================== - * ƒXƒe?ƒ^ƒXˆÙíƒ^ƒCƒ}?”Í??— - *------------------------------------------ - */ -int skill_status_change_timer_sub(struct block_list *bl, va_list ap ) -{ - struct block_list *src; - int type; - unsigned int tick; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - type=va_arg(ap,int); - tick=va_arg(ap,unsigned int); - - if(bl->type!=BL_PC && bl->type!=BL_MOB) - return 0; - - switch( type ){ - case SC_SIGHT: /* ƒTƒCƒg */ - case SC_CONCENTRATE: - if( (*battle_get_option(bl))&6 ){ - skill_status_change_end( bl, SC_HIDING, -1); - skill_status_change_end( bl, SC_CLOAKING, -1); - } - break; - case SC_RUWACH: /* ƒ‹ƒAƒt */ - if( (*battle_get_option(bl))&6 ){ - skill_status_change_end( bl, SC_HIDING, -1); - skill_status_change_end( bl, SC_CLOAKING, -1); - if(battle_check_target( src,bl, BCT_ENEMY ) > 0) { - struct status_change *sc_data = battle_get_sc_data(bl); - skill_attack(BF_MAGIC,src,src,bl,AL_RUWACH,sc_data[type].val1,tick,0); - } - } - break; - } - return 0; -} - -/*========================================== - * ƒXƒe?ƒ^ƒXˆÙíI—¹ - *------------------------------------------ - */ -int skill_status_change_end(struct block_list* bl, int type, int tid) -{ - struct status_change* sc_data; - int opt_flag=0, calc_flag = 0; - short *sc_count, *option, *opt1, *opt2, *opt3; - - nullpo_retr(0, bl); - if(bl->type!=BL_PC && bl->type!=BL_MOB) { - if(battle_config.error_log) - printf("skill_status_change_end: neither MOB nor PC !\n"); - return 0; - } - nullpo_retr(0, sc_data = battle_get_sc_data(bl)); - nullpo_retr(0, sc_count = battle_get_sc_count(bl)); - nullpo_retr(0, option = battle_get_option(bl)); - nullpo_retr(0, opt1 = battle_get_opt1(bl)); - nullpo_retr(0, opt2 = battle_get_opt2(bl)); - nullpo_retr(0, opt3 = battle_get_opt3(bl)); - - if ((*sc_count) > 0 && sc_data[type].timer != -1 && (sc_data[type].timer == tid || tid == -1)) { - - if (tid == -1) // ƒ^ƒCƒ}‚©‚çŒÄ‚΂ê‚Ä‚¢‚È‚¢‚È‚çƒ^ƒCƒ}íœ‚ð‚·‚é - delete_timer(sc_data[type].timer,skill_status_change_timer); - - /* ŠY?‚̈Ùí‚ð³í‚É?‚· */ - sc_data[type].timer=-1; - (*sc_count)--; - - switch(type){ /* ˆÙí‚ÌŽí—Þ‚²‚Æ‚Ì?— */ - case SC_PROVOKE: /* ƒvƒƒ{ƒbƒN */ - case SC_ENDURE: // celest - case SC_CONCENTRATE: /* W’†—ÍŒüã */ - case SC_BLESSING: /* ƒuƒŒƒbƒVƒ“ƒO */ - case SC_ANGELUS: /* ƒAƒ“ƒ[ƒ‹ƒX */ - case SC_INCREASEAGI: /* ‘¬“x㸠*/ - case SC_DECREASEAGI: /* ‘¬“xŒ¸ */ - case SC_SIGNUMCRUCIS: /* ƒVƒOƒiƒ€ƒNƒ‹ƒVƒX */ - case SC_HIDING: - case SC_TWOHANDQUICKEN: /* 2HQ */ - case SC_ADRENALINE: /* ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… */ - case SC_ENCPOISON: /* ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“ */ - case SC_IMPOSITIO: /* ƒCƒ“ƒ|ƒVƒeƒBƒIƒ}ƒkƒX */ - case SC_GLORIA: /* ƒOƒƒŠƒA */ - case SC_LOUD: /* ƒ‰ƒEƒhƒ{ƒCƒX */ - case SC_QUAGMIRE: /* ƒNƒ@ƒOƒ}ƒCƒA */ - case SC_PROVIDENCE: /* ƒvƒƒ”ƒBƒfƒ“ƒX */ - case SC_SPEARSQUICKEN: /* ƒXƒsƒAƒNƒCƒbƒPƒ“ */ - case SC_VOLCANO: - case SC_DELUGE: - case SC_VIOLENTGALE: - case SC_ETERNALCHAOS: /* ƒGƒ^?ƒiƒ‹ƒJƒIƒX */ - case SC_DRUMBATTLE: /* ?‘¾ŒÛ‚Ì‹¿‚« */ - case SC_NIBELUNGEN: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ - case SC_SIEGFRIED: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ - case SC_WHISTLE: /* Œû“J */ - case SC_ASSNCROS: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX */ - case SC_HUMMING: /* ƒnƒ~ƒ“ƒO */ - case SC_DONTFORGETME: /* Ž„‚ð–Y‚ê‚È‚¢‚Å */ - case SC_FORTUNE: /* K‰^‚̃LƒX */ - case SC_SERVICE4U: /* ƒT?ƒrƒXƒtƒH?ƒ†? */ - case SC_EXPLOSIONSPIRITS: // ”š—ô”g“® - case SC_STEELBODY: // ‹à„ - case SC_DEFENDER: - case SC_SPEEDPOTION0: /* ?‘¬ƒ|?ƒVƒ‡ƒ“ */ - case SC_SPEEDPOTION1: - case SC_SPEEDPOTION2: - case SC_APPLEIDUN: /* ƒCƒhƒDƒ“‚Ì—ÑŒç */ - case SC_RIDING: - case SC_BLADESTOP_WAIT: - case SC_AURABLADE: /* ƒI?ƒ‰ƒuƒŒ?ƒh */ - case SC_PARRYING: /* ƒpƒŠƒCƒ“ƒO */ - case SC_CONCENTRATION: /* ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ */ - case SC_TENSIONRELAX: /* ƒeƒ“ƒVƒ‡ƒ“ƒŠƒ‰ƒbƒNƒX */ - case SC_ASSUMPTIO: /* ƒAƒVƒƒƒ“ƒvƒeƒBƒI */ - case SC_WINDWALK: /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ - case SC_TRUESIGHT: /* ƒgƒDƒ‹?ƒTƒCƒg */ - case SC_SPIDERWEB: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ - case SC_MAGICPOWER: /* –‚–@—Í?• */ - case SC_CHASEWALK: - case SC_ATKPOT: /* attack potion [Valaris] */ - case SC_MATKPOT: /* magic attack potion [Valaris] */ - case SC_WEDDING: //Œ‹¥—p(Œ‹¥ˆßւɂȂÁ‚Ä?‚‚Ì‚ª?‚¢‚Æ‚©) - case SC_MELTDOWN: /* ƒƒ‹ƒgƒ_ƒEƒ“ */ - // Celest - case SC_EDP: - case SC_MARIONETTE: - case SC_MARIONETTE2: - case SC_SLOWDOWN: - case SC_LEADERSHIP: - case SC_GLORYWOUNDS: - case SC_SOULCOLD: - case SC_HAWKEYES: - case SC_BATTLEORDERS: - case SC_REGENERATION: - calc_flag = 1; - break; - case SC_BERSERK: /* ƒo?ƒT?ƒN */ - calc_flag = 1; - clif_status_change(bl,SC_INCREASEAGI,0); /* ƒAƒCƒRƒ“Á‹Ž */ - break; - case SC_DEVOTION: /* ƒfƒBƒ{?ƒVƒ‡ƒ“ */ - { - struct map_session_data *md = map_id2sd(sc_data[type].val1); - sc_data[type].val1=sc_data[type].val2=0; - skill_devotion(md,bl->id); - calc_flag = 1; - } - break; - case SC_BLADESTOP: - { - struct status_change *t_sc_data = battle_get_sc_data((struct block_list *)sc_data[type].val4); - //•Еû‚ªØ‚ꂽ‚Ì‚Å‘ŠŽè‚Ì”’n?‘Ô‚ªØ‚ê‚ĂȂ¢‚̂Ȃç‰ðœ - if(t_sc_data && t_sc_data[SC_BLADESTOP].timer!=-1) - skill_status_change_end((struct block_list *)sc_data[type].val4,SC_BLADESTOP,-1); - - if(sc_data[type].val2==2) - clif_bladestop((struct block_list *)sc_data[type].val3,(struct block_list *)sc_data[type].val4,0); - } - break; - case SC_DANCING: - { - struct map_session_data *dsd; - struct status_change *d_sc_data; - if(sc_data[type].val4 && (dsd=map_id2sd(sc_data[type].val4))){ - d_sc_data = dsd->sc_data; - //‡‘t‚Å‘ŠŽè‚ª‚¢‚éê‡‘ŠŽè‚Ìval4‚ð0‚É‚·‚é - if(d_sc_data && d_sc_data[type].timer!=-1) - d_sc_data[type].val4=0; - } - } - calc_flag = 1; - break; - case SC_GRAFFITI: - { - struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[type].val4; //val4‚ªƒOƒ‰ƒtƒBƒeƒB‚Ìgroup_id - if(sg) - skill_delunitgroup(sg); - } - break; - case SC_NOCHAT: //ƒ`ƒƒƒbƒg‹ÖŽ~?‘Ô - { - struct map_session_data *sd=NULL; - if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)){ - if (sd->status.manner >= 0) // weeee ^^ [celest] - sd->status.manner = 0; - clif_updatestatus(sd,SP_MANNER); - } - } - break; - case SC_SPLASHER: /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ? */ - { - struct block_list *src=map_id2bl(sc_data[type].val3); - if(src && tid!=-1){ - //Ž©•ª‚Ƀ_ƒ?ƒW•Žü?3*3‚Ƀ_ƒ?ƒW - skill_castend_damage_id(src, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 ); - } - } - break; - case SC_SELFDESTRUCTION: /* Ž©”š */ - { - //Ž©•ª‚̃_ƒ?ƒW‚Í0‚É‚µ‚Ä - struct mob_data *md=NULL; - if(bl->type == BL_MOB && (md=(struct mob_data*)bl)) - skill_castend_damage_id(bl, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 ); - } - break; - /* option1 */ - case SC_FREEZE: - sc_data[type].val3 = 0; - break; - - /* option2 */ - case SC_POISON: /* “Å */ - case SC_BLIND: /* ˆÃ? */ - case SC_CURSE: - calc_flag = 1; - break; - } - - if(bl->type==BL_PC && type<SC_SENDMAX) - clif_status_change(bl,type,0); /* ƒAƒCƒRƒ“Á‹Ž */ - - switch(type){ /* ³í‚É?‚邯‚«‚Ȃɂ©?—‚ª•K—v */ - case SC_STONE: - case SC_FREEZE: - case SC_STAN: - case SC_SLEEP: - *opt1 = 0; - opt_flag = 1; - break; - - case SC_POISON: - if (sc_data[SC_DPOISON].timer != -1) // - break; // DPOISON—p‚̃IƒvƒVƒ‡ƒ“ - *opt2 &= ~1; // ‚ª?—p‚É—pˆÓ‚³‚ê‚½ê‡‚É‚Í - opt_flag = 1; // ‚±‚±‚Í휂·‚é - break; // - case SC_CURSE: - case SC_SILENCE: - case SC_BLIND: - *opt2 &= ~(1<<(type-SC_POISON)); - opt_flag = 1; - break; - case SC_DPOISON: - if (sc_data[SC_POISON].timer != -1) // DPOISON—p‚̃IƒvƒVƒ‡ƒ“‚ª - break; // —pˆÓ‚³‚ꂽ‚çíœ - *opt2 &= ~1; // “Å?‘Ô‰ðœ - opt_flag = 1; - break; - case SC_SIGNUMCRUCIS: - *opt2 &= ~0x40; - opt_flag = 1; - break; - - case SC_HIDING: - case SC_CLOAKING: - *option &= ~((type == SC_HIDING) ? 2 : 4); - calc_flag = 1; // orn - opt_flag = 1 ; - break; - - case SC_CHASEWALK: - *option &= ~16388; - opt_flag = 1 ; - break; - - case SC_SIGHT: - *option &= ~1; - opt_flag = 1; - break; - case SC_WEDDING: //Œ‹¥—p(Œ‹¥ˆßւɂȂÁ‚Ä?‚‚Ì‚ª?‚¢‚Æ‚©) - *option &= ~4096; - opt_flag = 1; - break; - case SC_RUWACH: - *option &= ~8192; - opt_flag = 1; - break; - - //opt3 - case SC_TWOHANDQUICKEN: /* 2HQ */ - case SC_SPEARSQUICKEN: /* ƒXƒsƒAƒNƒCƒbƒPƒ“ */ - case SC_CONCENTRATION: /* ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ */ - *opt3 &= ~1; - break; - case SC_OVERTHRUST: /* ƒI?ƒo?ƒXƒ‰ƒXƒg */ - *opt3 &= ~2; - break; - case SC_ENERGYCOAT: /* ƒGƒiƒW?ƒR?ƒg */ - *opt3 &= ~4; - break; - case SC_EXPLOSIONSPIRITS: // ”š—ô”g“® - *opt3 &= ~8; - break; - case SC_STEELBODY: // ‹à„ - *opt3 &= ~16; - break; - case SC_BLADESTOP: /* ”’nŽæ‚è */ - *opt3 &= ~32; - break; - case SC_BERSERK: /* ƒo?ƒT?ƒN */ - *opt3 &= ~128; - break; - case SC_MARIONETTE: /* ƒ}ƒŠƒIƒlƒbƒgƒRƒ“ƒgƒ?ƒ‹ */ - case SC_MARIONETTE2: - *opt3 &= ~1024; - break; - case SC_ASSUMPTIO: /* ƒAƒXƒ€ƒvƒeƒBƒI */ - *opt3 &= ~2048; - break; - } - - if (night_flag == 1 && (*opt2 & STATE_BLIND) == 0 && bl->type == BL_PC && // by [Yor] - !map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) { // [celest] - *opt2 |= STATE_BLIND; - opt_flag = 1; - } - - if(opt_flag) /* option‚Ì?X‚ð?‚¦‚é */ - clif_changeoption(bl); - - if (bl->type == BL_PC && calc_flag) - pc_calcstatus((struct map_session_data *)bl,0); /* ƒXƒe?ƒ^ƒXÄŒvŽZ */ - } - - return 0; -} -/*========================================== - * ƒXƒe?ƒ^ƒXˆÙíI—¹ƒ^ƒCƒ}? - *------------------------------------------ - */ -int skill_status_change_timer(int tid, unsigned int tick, int id, int data) -{ - int type=data; - struct block_list *bl; - struct map_session_data *sd=NULL; - struct status_change *sc_data; - //short *sc_count; //Žg‚Á‚ĂȂ¢H - - if( (bl=map_id2bl(id)) == NULL ) - return 0; //ŠY?ID‚ª‚·‚Å‚ÉÁ–Å‚µ‚Ä‚¢‚邯‚¢‚¤‚̂͂¢‚©‚É‚à‚ ‚è‚»‚¤‚Ȃ̂ŃXƒ‹?‚µ‚Ă݂é - nullpo_retr(0, sc_data=battle_get_sc_data(bl)); - - if(bl->type==BL_PC) - sd=(struct map_session_data *)bl; - - //sc_count=battle_get_sc_count(bl); //Žg‚Á‚ĂȂ¢H - - if(sc_data[type].timer != tid) { - if(battle_config.error_log) - printf("skill_status_change_timer %d != %d\n",tid,sc_data[type].timer); - } - - switch(type){ /* “ÁŽê‚È?—‚ɂȂéê‡ */ - case SC_MAXIMIZEPOWER: /* ƒ}ƒLƒVƒ}ƒCƒYƒpƒ? */ - case SC_CLOAKING: - if(sd){ - if( sd->status.sp > 0 ){ /* SPØ‚ê‚é‚܂Ŏ? */ - sd->status.sp--; - clif_updatestatus(sd,SP_SP); - sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ - sc_data[type].val2+tick, skill_status_change_timer, bl->id, data); - return 0; - } - } - break; - - case SC_CHASEWALK: - if(sd){ - if( sd->status.sp > 19+sc_data[SC_CHASEWALK].val1*3){ - sd->status.sp-=(19+(sc_data[SC_CHASEWALK].val1*3)); // update sp cost [Celest] - clif_updatestatus(sd,SP_SP); - sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ - sc_data[type].val2+tick, skill_status_change_timer, bl->id, data); - return 0; - } - } - break; - - case SC_HIDING: /* ƒnƒCƒfƒBƒ“ƒO */ - if(sd){ /* SP‚ª‚ ‚Á‚ÄAŽžŠÔ§ŒÀ‚ÌŠÔ‚ÍŽ? */ - if( sd->status.sp > 0 && (--sc_data[type].val2)>0 ){ - if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){ - sd->status.sp--; - clif_updatestatus(sd,SP_SP); - } - sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ - 1000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - - case SC_SIGHT: /* ƒTƒCƒg */ - { - const int range=7; - map_foreachinarea( skill_status_change_timer_sub, - bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0, - bl,type,tick); - - if( (--sc_data[type].val2)>0 ){ - sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ - 250+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - case SC_RUWACH: /* ƒ‹ƒAƒt */ - { - const int range=5; - map_foreachinarea( skill_status_change_timer_sub, - bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0, - bl,type,tick); - - if( (--sc_data[type].val2)>0 ){ - sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ - 250+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - - case SC_SIGNUMCRUCIS: /* ƒVƒOƒiƒ€ƒNƒ‹ƒVƒX */ - { - int race = battle_get_race(bl); - if(race == 6 || battle_check_undead(race,battle_get_elem_type(bl))) { - sc_data[type].timer=add_timer(1000*600+tick,skill_status_change_timer, bl->id, data ); - return 0; - } - } - break; - - case SC_PROVOKE: /* ƒvƒƒ{ƒbƒN/ƒI?ƒgƒo?ƒT?ƒN */ - if(sc_data[type].val2!=0){ /* ƒI?ƒgƒo?ƒT?ƒNi‚P•b‚²‚Æ‚ÉHPƒ`ƒFƒbƒNj */ - if(sd && sd->status.hp>sd->status.max_hp>>2) /* ’âŽ~ */ - break; - sc_data[type].timer=add_timer( 1000+tick,skill_status_change_timer, bl->id, data ); - return 0; - } - break; - - case SC_WATERBALL: /* ƒEƒH?ƒ^?ƒ{?ƒ‹ */ - { - struct block_list *target=map_id2bl(sc_data[type].val2); - if(target==NULL || target->prev==NULL) - break; - skill_attack(BF_MAGIC,bl,bl,target,WZ_WATERBALL,sc_data[type].val1,tick,0); - if((--sc_data[type].val3)>0) { - sc_data[type].timer=add_timer( 150+tick,skill_status_change_timer, bl->id, data ); - return 0; - } - } - break; - - case SC_ENDURE: /* ƒCƒ“ƒfƒ…ƒA */ - if(sd && sd->special_state.infinite_endure) { - sc_data[type].timer=add_timer( 1000*60+tick,skill_status_change_timer, bl->id, data ); - //sc_data[type].val2=1; - return 0; - } - break; - - case SC_DISSONANCE: /* •s‹¦˜a‰¹ */ - if( (--sc_data[type].val2)>0){ - struct skill_unit *unit= - (struct skill_unit *)sc_data[type].val4; - struct block_list *src; - - if(!unit || !unit->group) - break; - src=map_id2bl(unit->group->src_id); - if(!src) - break; - skill_attack(BF_MISC,src,&unit->bl,bl,unit->group->skill_id,sc_data[type].val1,tick,0); - sc_data[type].timer=add_timer(skill_get_time2(unit->group->skill_id,unit->group->skill_lv)+tick, - skill_status_change_timer, bl->id, data ); - return 0; - } - break; - - case SC_LULLABY: /* ŽqŽç‰S */ - if( (--sc_data[type].val2)>0){ - struct skill_unit *unit= - (struct skill_unit *)sc_data[type].val4; - if(!unit || !unit->group || unit->group->src_id==bl->id) - break; - skill_additional_effect(bl,bl,unit->group->skill_id,sc_data[type].val1,BF_LONG|BF_SKILL|BF_MISC,tick); - sc_data[type].timer=add_timer(skill_get_time(unit->group->skill_id,unit->group->skill_lv)/10+tick, - skill_status_change_timer, bl->id, data ); - return 0; - } - break; - - case SC_STONE: - if(sc_data[type].val2 != 0) { - short *opt1 = battle_get_opt1(bl); - sc_data[type].val2 = 0; - sc_data[type].val4 = 0; - battle_stopwalking(bl,1); - if(opt1) { - *opt1 = 1; - clif_changeoption(bl); - } - sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data ); - return 0; - } - else if( (--sc_data[type].val3) > 0) { - int hp = battle_get_max_hp(bl); - if((++sc_data[type].val4)%5 == 0 && battle_get_hp(bl) > hp>>2) { - hp = hp/100; - if(hp < 1) hp = 1; - if(bl->type == BL_PC) - pc_heal((struct map_session_data *)bl,-hp,0); - else if(bl->type == BL_MOB){ - struct mob_data *md; - if((md=((struct mob_data *)bl)) == NULL) - break; - md->hp -= hp; - } - } - sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data ); - return 0; - } - break; - case SC_POISON: - if(sc_data[SC_SLOWPOISON].timer == -1) { - if( (--sc_data[type].val3) > 0) { - int hp = battle_get_max_hp(bl); - if(battle_get_hp(bl) > hp>>2) { - if(bl->type == BL_PC) { - hp = 3 + hp*3/200; - pc_heal((struct map_session_data *)bl,-hp,0); - } - else if(bl->type == BL_MOB) { - struct mob_data *md; - if((md=((struct mob_data *)bl)) == NULL) - break; - hp = 3 + hp/200; - md->hp -= hp; - } - } - sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data ); - } - } - else - sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data ); - break; - case SC_DPOISON: - if (sc_data[SC_SLOWPOISON].timer == -1 && (--sc_data[type].val3) > 0) { - int hp = battle_get_max_hp(bl); - if (battle_get_hp(bl) > hp>>2) { - if(bl->type == BL_PC) { - hp = 3 + hp/50; - pc_heal((struct map_session_data *)bl, -hp, 0); - } else if (bl->type == BL_MOB) { - struct mob_data *md; - if ((md=((struct mob_data *)bl)) == NULL) - break; - hp = 3 + hp/100; - md->hp -= hp; - } - } - } - if (sc_data[type].val3 > 0) - sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data ); - break; - - case SC_TENSIONRELAX: /* ƒeƒ“ƒVƒ‡ƒ“ƒŠƒ‰ƒbƒNƒX */ - if(sd){ /* SP‚ª‚ ‚Á‚ÄAHP‚ª?ƒ^ƒ“‚łȂ¯‚ê‚Î?? */ - if( sd->status.sp > 12 && sd->status.max_hp > sd->status.hp ){ -/* if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){ - sd->status.sp -= 12; - clif_updatestatus(sd,SP_SP); - } */ - sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ - 10000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - if(sd->status.max_hp <= sd->status.hp) - skill_status_change_end(&sd->bl,SC_TENSIONRELAX,-1); - } - break; - case SC_HEADCRUSH: // temporary damage [celest] -// case SC_BLEEDING: - if((--sc_data[type].val3) > 0) { - int hp = battle_get_max_hp(bl); - if(bl->type == BL_PC) { - hp = 3 + hp*3/200; - pc_heal((struct map_session_data *)bl,-hp,0); - } - else if(bl->type == BL_MOB) { - struct mob_data *md; - if((md=((struct mob_data *)bl)) == NULL) - break; - hp = 3 + hp/200; - md->hp -= hp; - } - sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data ); - } - break; - - /* ŽžŠÔ؂ꖳ‚µHH */ - case SC_AETERNA: - case SC_TRICKDEAD: - case SC_RIDING: - case SC_FALCON: - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_MAGICPOWER: /* –‚–@—Í?• */ - case SC_REJECTSWORD: /* ƒŠƒWƒFƒNƒgƒ\?ƒh */ - case SC_MEMORIZE: /* ƒƒ‚ƒ‰ƒCƒY */ - case SC_BROKNWEAPON: - case SC_BROKNARMOR: - if(sc_data[type].timer==tid) - sc_data[type].timer=add_timer( 1000*600+tick,skill_status_change_timer, bl->id, data ); - return 0; - - case SC_DANCING: //ƒ_ƒ“ƒXƒXƒLƒ‹‚ÌŽžŠÔSPÁ”ï - { - int s=0; - if(sd){ - if(sd->status.sp > 0 && (--sc_data[type].val3)>0){ - switch(sc_data[type].val1){ - case BD_RICHMANKIM: /* ƒjƒˆƒ‹ƒh‚̉ƒ 3•b‚ÉSP1 */ - case BD_DRUMBATTLEFIELD: /* ?‘¾ŒÛ‚Ì‹¿‚« 3•b‚ÉSP1 */ - case BD_RINGNIBELUNGEN: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö 3•b‚ÉSP1 */ - case BD_SIEGFRIED: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh 3•b‚ÉSP1 */ - case BA_DISSONANCE: /* •s‹¦˜a‰¹ 3•b‚ÅSP1 */ - case BA_ASSASSINCROSS: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX 3•b‚ÅSP1 */ - case DC_UGLYDANCE: /* Ž©•ªŸŽè‚ȃ_ƒ“ƒX 3•b‚ÅSP1 */ - s=3; - break; - case BD_LULLABY: /* ŽqŽç‰Ì 4•b‚ÉSP1 */ - case BD_ETERNALCHAOS: /* ‰i‰“‚̬“× 4•b‚ÉSP1 */ - case BD_ROKISWEIL: /* ƒƒL‚Ì‹©‚Ñ 4•b‚ÉSP1 */ - case DC_FORTUNEKISS: /* K‰^‚̃LƒX 4•b‚ÅSP1 */ - s=4; - break; - case BD_INTOABYSS: /* [•£‚Ì’†‚É 5•b‚ÉSP1 */ - case BA_WHISTLE: /* Œû“J 5•b‚ÅSP1 */ - case DC_HUMMING: /* ƒnƒ~ƒ“ƒO 5•b‚ÅSP1 */ - case BA_POEMBRAGI: /* ƒuƒ‰ƒM‚ÌŽ 5•b‚ÅSP1 */ - case DC_SERVICEFORYOU: /* ƒT?ƒrƒXƒtƒH?ƒ†? 5•b‚ÅSP1 */ - s=5; - break; - case BA_APPLEIDUN: /* ƒCƒhƒDƒ“‚Ì—ÑŒç 6•b‚ÅSP1 */ - s=6; - break; - case DC_DONTFORGETME: /* Ž„‚ð–Y‚ê‚È‚¢‚Åc 10•b‚ÅSP1 */ - case CG_MOONLIT: /* ŒŽ–¾‚è‚Ìò‚É—Ž‚¿‚é‰Ô‚Ñ‚ç 10•b‚ÅSP1H */ - s=10; - break; - } - if(s && ((sc_data[type].val3 % s) == 0)){ - sd->status.sp--; - clif_updatestatus(sd,SP_SP); - } - sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ - 1000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - } - break; - case SC_BERSERK: /* ƒo?ƒT?ƒN */ - if(sd){ /* HP‚ª100ˆÈã‚È‚ç?? */ - if( (sd->status.hp - sd->status.max_hp*5/100) > 100 ){ // 5% every 10 seconds [DracoRPG] - sd->status.hp -= sd->status.max_hp*5/100; // changed to max hp [celest] - clif_updatestatus(sd,SP_HP); - sc_data[type].timer = add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ - 10000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - case SC_WEDDING: //Œ‹¥—p(Œ‹¥ˆßւɂȂÁ‚Ä?‚‚Ì‚ª?‚¢‚Æ‚©) - if(sd){ - time_t timer; - if(time(&timer) < ((sc_data[type].val2) + 3600)){ //1ŽžŠÔ‚½‚Á‚Ä‚¢‚È‚¢‚Ì‚Å?? - sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ - 10000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - case SC_NOCHAT: //ƒ`ƒƒƒbƒg‹ÖŽ~?‘Ô - if(sd && battle_config.muting_players){ - time_t timer; - if((++sd->status.manner) && time(&timer) < ((sc_data[type].val2) + 60*(0-sd->status.manner))){ //ŠJŽn‚©‚çstatus.manner•ª?‚Á‚ĂȂ¢‚Ì‚Å?? - clif_updatestatus(sd,SP_MANNER); - sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è(60•b) */ - 60000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - case SC_SELFDESTRUCTION: /* Ž©”š */ - if(--sc_data[type].val3>0){ - struct mob_data *md; - if(bl->type==BL_MOB && (md=(struct mob_data *)bl) && md->speed > 250){ - md->speed -= 250; - md->next_walktime=tick; - } - sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ - 1000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - break; - case SC_LEADERSHIP: - case SC_GLORYWOUNDS: - case SC_SOULCOLD: - case SC_HAWKEYES: - if (sd) { - sc_data[type].timer = add_timer( - 1000+tick, skill_status_change_timer, - bl->id, data); - } - break; - } - - - - return skill_status_change_end( bl,type,tid ); -} /*========================================== * ƒXƒe?ƒ^ƒXˆÙíI—¹ *------------------------------------------ */ -int skill_encchant_eremental_end(struct block_list *bl,int type) +int skill_enchant_elemental_end (struct block_list *bl, int type) { struct status_change *sc_data; nullpo_retr(0, bl); - nullpo_retr(0, sc_data=battle_get_sc_data(bl)); - - if( type!=SC_ENCPOISON && sc_data[SC_ENCPOISON].timer!=-1 ) /* ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“‰ðœ */ - skill_status_change_end(bl,SC_ENCPOISON,-1); - if( type!=SC_ASPERSIO && sc_data[SC_ASPERSIO].timer!=-1 ) /* ƒAƒXƒyƒ‹ƒVƒI‰ðœ */ - skill_status_change_end(bl,SC_ASPERSIO,-1); - if( type!=SC_FLAMELAUNCHER && sc_data[SC_FLAMELAUNCHER].timer!=-1 ) /* ƒtƒŒƒCƒ€ƒ‰ƒ“ƒ`ƒƒ‰ðœ */ - skill_status_change_end(bl,SC_FLAMELAUNCHER,-1); - if( type!=SC_FROSTWEAPON && sc_data[SC_FROSTWEAPON].timer!=-1 ) /* ƒtƒƒXƒgƒEƒFƒ|ƒ“‰ðœ */ - skill_status_change_end(bl,SC_FROSTWEAPON,-1); - if( type!=SC_LIGHTNINGLOADER && sc_data[SC_LIGHTNINGLOADER].timer!=-1 ) /* ƒ‰ƒCƒgƒjƒ“ƒOƒ?ƒ_?‰ðœ */ - skill_status_change_end(bl,SC_LIGHTNINGLOADER,-1); - if( type!=SC_SEISMICWEAPON && sc_data[SC_SEISMICWEAPON].timer!=-1 ) /* ƒTƒCƒXƒ~ƒbƒNƒEƒFƒ|ƒ“‰ðœ */ - skill_status_change_end(bl,SC_SEISMICWEAPON,-1); + nullpo_retr(0, sc_data = status_get_sc_data(bl)); + + if (type != SC_ENCPOISON && sc_data[SC_ENCPOISON].timer != -1) /* ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“‰ðœ */ + status_change_end(bl, SC_ENCPOISON, -1); + if (type != SC_ASPERSIO && sc_data[SC_ASPERSIO].timer != -1) /* ƒAƒXƒyƒ‹ƒVƒI‰ðœ */ + status_change_end(bl, SC_ASPERSIO, -1); + if (type != SC_FLAMELAUNCHER && sc_data[SC_FLAMELAUNCHER].timer != -1) /* ƒtƒŒƒCƒ€ƒ‰ƒ“ƒ`ƒƒ‰ðœ */ + status_change_end(bl, SC_FLAMELAUNCHER, -1); + if (type != SC_FROSTWEAPON && sc_data[SC_FROSTWEAPON].timer != -1) /* ƒtƒƒXƒgƒEƒFƒ|ƒ“‰ðœ */ + status_change_end(bl, SC_FROSTWEAPON, -1); + if (type != SC_LIGHTNINGLOADER && sc_data[SC_LIGHTNINGLOADER].timer != -1) /* ƒ‰ƒCƒgƒjƒ“ƒOƒ?ƒ_?‰ðœ */ + status_change_end(bl, SC_LIGHTNINGLOADER, -1); + if (type != SC_SEISMICWEAPON && sc_data[SC_SEISMICWEAPON].timer != -1) /* ƒTƒCƒXƒ~ƒbƒNƒEƒFƒ|ƒ“‰ðœ */ + status_change_end(bl, SC_SEISMICWEAPON, -1); return 0; } -/*========================================== - * ƒXƒe?ƒ^ƒXˆÙíŠJŽn - *------------------------------------------ - */ -int skill_status_change_start(struct block_list *bl, int type, int val1, int val2, int val3, int val4, int tick, int flag) + +/* ƒNƒ?ƒLƒ“ƒO?¸iŽü‚è‚Ɉړ®•s‰Â”\’n?‚ª‚ ‚é‚©j */ +int skill_check_cloaking(struct block_list *bl) { struct map_session_data *sd = NULL; - struct status_change* sc_data; - short *sc_count, *option, *opt1, *opt2, *opt3; - int opt_flag = 0, calc_flag = 0,updateflag = 0, save_flag = 0, race, mode, elem, undead_flag; - int scdef=0; - - nullpo_retr(0, bl); - if(bl->type == BL_SKILL) - return 0; - nullpo_retr(0, sc_data=battle_get_sc_data(bl)); - nullpo_retr(0, sc_count=battle_get_sc_count(bl)); - nullpo_retr(0, option=battle_get_option(bl)); - nullpo_retr(0, opt1=battle_get_opt1(bl)); - nullpo_retr(0, opt2=battle_get_opt2(bl)); - nullpo_retr(0, opt3=battle_get_opt3(bl)); - - - race=battle_get_race(bl); - mode=battle_get_mode(bl); - elem=battle_get_elem_type(bl); - undead_flag=battle_check_undead(race,elem); - - if(type == SC_AETERNA && (sc_data[SC_STONE].timer != -1 || sc_data[SC_FREEZE].timer != -1) ) - return 0; - - switch(type){ - case SC_STONE: - case SC_FREEZE: - scdef=3+battle_get_mdef(bl)+battle_get_luk(bl)/3; - break; - case SC_STAN: - case SC_SILENCE: - case SC_POISON: - case SC_DPOISON: - scdef=3+battle_get_vit(bl)+battle_get_luk(bl)/3; - break; - case SC_SLEEP: - case SC_BLIND: - scdef=3+battle_get_int(bl)+battle_get_luk(bl)/3; - break; - case SC_CURSE: - scdef=3+battle_get_luk(bl); - break; - -// case SC_CONFUSION: - default: - scdef=0; - } - if(scdef>=100) - return 0; - if(bl->type==BL_PC){ - sd=(struct map_session_data *)bl; - if( sd && type == SC_ADRENALINE && !(skill_get_weapontype(BS_ADRENALINE)&(1<<sd->status.weapon))) - return 0; - - if(SC_STONE<=type && type<=SC_BLIND){ /* ƒJ?ƒh‚É‚æ‚é‘Ï« */ - if( sd && sd->reseff[type-SC_STONE] > 0 && rand()%10000<sd->reseff[type-SC_STONE]){ - if(battle_config.battle_log) - printf("PC %d skill_sc_start: card‚É‚æ‚éˆÙí‘Ï«?“®\n",sd->bl.id); - return 0; - } - } - } - else if(bl->type == BL_MOB) { - } - else { - if(battle_config.error_log) - printf("skill_status_change_start: neither MOB nor PC !\n"); - return 0; - } - - if(type==SC_FREEZE && undead_flag && !(flag&1)) - return 0; - - if((type == SC_ADRENALINE || type == SC_WEAPONPERFECTION || type == SC_OVERTHRUST) && - sc_data[type].timer != -1 && sc_data[type].val2 && !val2) - return 0; - - if(mode & 0x20 && (type==SC_STONE || type==SC_FREEZE || - type==SC_STAN || type==SC_SLEEP || type==SC_SILENCE || type==SC_QUAGMIRE || type == SC_DECREASEAGI || type == SC_SIGNUMCRUCIS || type == SC_PROVOKE || - (type == SC_BLESSING && (undead_flag || race == 6))) && !(flag&1)){ - /* ƒ{ƒX‚É‚Í?‚©‚È‚¢(‚½‚¾‚µƒJ?ƒh‚É‚æ‚é?‰Ê‚Í“K—p‚³‚ê‚é) */ - return 0; - } - if(type==SC_FREEZE || type==SC_STAN || type==SC_SLEEP) - battle_stopwalking(bl,1); + static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus + static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1}; + int end = 1,i; - if(sc_data[type].timer != -1){ /* ‚·‚łɓ¯‚¶ˆÙí‚ɂȂÁ‚Ä‚¢‚éꇃ^ƒCƒ}‰ðœ */ - if(sc_data[type].val1 > val1 && type != SC_COMBO && type != SC_DANCING && type != SC_DEVOTION && - type != SC_SPEEDPOTION0 && type != SC_SPEEDPOTION1 && type != SC_SPEEDPOTION2 - && type != SC_ATKPOT && type != SC_MATKPOT) // added atk and matk potions [Valaris] - return 0; - if(type >=SC_STAN && type <= SC_BLIND) - return 0;/* ?‚¬‘«‚µ‚ª‚Å‚«‚È‚¢?‘ÔˆÙí‚Å‚ ‚鎞‚Í?‘ÔˆÙí‚ðs‚í‚È‚¢ */ - if(type == SC_GRAFFITI){ //ˆÙí’†‚É‚à‚¤ˆê“x?‘ÔˆÙí‚ɂȂÁ‚½Žž‚ɉ𜂵‚Ä‚©‚çÄ“x‚©‚©‚é - skill_status_change_end(bl,type,-1); - } else { - (*sc_count)--; - delete_timer(sc_data[type].timer, skill_status_change_timer); - sc_data[type].timer = -1; - } - } - - switch(type){ /* ˆÙí‚ÌŽí—Þ‚²‚Æ‚Ì?— */ - case SC_PROVOKE: /* ƒvƒƒ{ƒbƒN */ - calc_flag = 1; - if(tick <= 0) tick = 1000; /* (ƒI?ƒgƒo?ƒT?ƒN) */ - break; - case SC_ENDURE: /* ƒCƒ“ƒfƒ…ƒA */ - if(tick <= 0) tick = 1000 * 60; - calc_flag = 1; // for updating mdef - val2 = 7; // [Celest] - break; - case SC_CONCENTRATE: /* W’†—ÍŒüã */ - calc_flag = 1; - break; - case SC_BLESSING: /* ƒuƒŒƒbƒVƒ“ƒO */ - { - if(bl->type == BL_PC || (!undead_flag && race != 6)) { - if(sc_data[SC_CURSE].timer!=-1 ) - skill_status_change_end(bl,SC_CURSE,-1); - if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2 == 0) - skill_status_change_end(bl,SC_STONE,-1); - } - calc_flag = 1; - } - break; - case SC_ANGELUS: /* ƒAƒ“ƒ[ƒ‹ƒX */ - calc_flag = 1; - break; - case SC_INCREASEAGI: /* ‘¬“x㸠*/ - calc_flag = 1; - if(sc_data[SC_DECREASEAGI].timer!=-1 ) - skill_status_change_end(bl,SC_DECREASEAGI,-1); - if(sc_data[SC_WINDWALK].timer!=-1 ) /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ - skill_status_change_end(bl,SC_WINDWALK,-1); - break; - case SC_DECREASEAGI: /* ‘¬“xŒ¸ */ - if (bl->type == BL_PC) // Celest - tick>>=1; - calc_flag = 1; - if(sc_data[SC_INCREASEAGI].timer!=-1 ) - skill_status_change_end(bl,SC_INCREASEAGI,-1); - if(sc_data[SC_ADRENALINE].timer!=-1 ) - skill_status_change_end(bl,SC_ADRENALINE,-1); - if(sc_data[SC_SPEARSQUICKEN].timer!=-1 ) - skill_status_change_end(bl,SC_SPEARSQUICKEN,-1); - if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 ) - skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1); - break; - case SC_SIGNUMCRUCIS: /* ƒVƒOƒiƒ€ƒNƒ‹ƒVƒX */ - calc_flag = 1; -// val2 = 14 + val1; - val2 = 10 + val1*2; - tick = 600*1000; - clif_emotion(bl,4); - break; - case SC_SLOWPOISON: - if (sc_data[SC_POISON].timer == -1 && sc_data[SC_DPOISON].timer == -1) - return 0; - break; - case SC_TWOHANDQUICKEN: /* 2HQ */ - if(sc_data[SC_DECREASEAGI].timer!=-1) - return 0; - *opt3 |= 1; - calc_flag = 1; - break; - case SC_ADRENALINE: /* ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… */ - if(sc_data[SC_DECREASEAGI].timer!=-1) - return 0; - calc_flag = 1; - break; - case SC_WEAPONPERFECTION: /* ƒEƒFƒ|ƒ“ƒp?ƒtƒFƒNƒVƒ‡ƒ“ */ - if(battle_config.party_skill_penaly && !val2) tick /= 5; - break; - case SC_OVERTHRUST: /* ƒI?ƒo?ƒXƒ‰ƒXƒg */ - *opt3 |= 2; - if(battle_config.party_skill_penaly && !val2) tick /= 10; - break; - case SC_MAXIMIZEPOWER: /* ƒ}ƒLƒVƒ}ƒCƒYƒpƒ?(SP‚ª1Œ¸‚鎞ŠÔ,val2‚É‚à) */ - if(bl->type == BL_PC) - val2 = tick; - else - tick = 5000*val1; - break; - case SC_ENCPOISON: /* ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“ */ - calc_flag = 1; - val2=(((val1 - 1) / 2) + 3)*100; /* “Å•t?Šm—¦ */ - skill_encchant_eremental_end(bl,SC_ENCPOISON); - break; - case SC_EDP: // [Celest] - val2 = val1 + 2; /* –Ò“Å•t?Šm—¦(%) */ - calc_flag = 1; - break; - case SC_POISONREACT: /* ƒ|ƒCƒYƒ“ƒŠƒAƒNƒg */ - val2=val1/2 + val1%2; // [Celest] - break; - case SC_IMPOSITIO: /* ƒCƒ“ƒ|ƒVƒeƒBƒIƒ}ƒkƒX */ - calc_flag = 1; - break; - case SC_ASPERSIO: /* ƒAƒXƒyƒ‹ƒVƒI */ - skill_encchant_eremental_end(bl,SC_ASPERSIO); - break; - case SC_SUFFRAGIUM: /* ƒTƒtƒ‰ƒMƒ€ */ - case SC_BENEDICTIO: /* ¹? */ - case SC_MAGNIFICAT: /* ƒ}ƒOƒjƒtƒBƒJ?ƒg */ - case SC_AETERNA: /* ƒG?ƒeƒ‹ƒi */ - break; - case SC_ENERGYCOAT: /* ƒGƒiƒW?ƒR?ƒg */ - *opt3 |= 4; - break; - case SC_MAGICROD: - val2 = val1*20; - break; - case SC_KYRIE: /* ƒLƒŠƒGƒGƒŒƒCƒ\ƒ“ */ - val2 = battle_get_max_hp(bl) * (val1 * 2 + 10) / 100;/* ‘Ï‹v“x */ - val3 = (val1 / 2 + 5); /* ‰ñ? */ -// -- moonsoul (added to undo assumptio status if target has it) - if(sc_data[SC_ASSUMPTIO].timer!=-1 ) - skill_status_change_end(bl,SC_ASSUMPTIO,-1); - break; - case SC_MINDBREAKER: - calc_flag = 1; - if(tick <= 0) tick = 1000; /* (ƒI?ƒgƒo?ƒT?ƒN) */ - case SC_GLORIA: /* ƒOƒƒŠƒA */ - calc_flag = 1; - break; - case SC_LOUD: /* ƒ‰ƒEƒhƒ{ƒCƒX */ - calc_flag = 1; - break; - case SC_TRICKDEAD: /* Ž€‚ñ‚¾‚Ó‚è */ - break; - case SC_QUAGMIRE: /* ƒNƒ@ƒOƒ}ƒCƒA */ - calc_flag = 1; - if(sc_data[SC_CONCENTRATE].timer!=-1 ) /* W’†—ÍŒüã‰ðœ */ - skill_status_change_end(bl,SC_CONCENTRATE,-1); - if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* ‘¬“x㸉ðœ */ - skill_status_change_end(bl,SC_INCREASEAGI,-1); - if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 ) - skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1); - if(sc_data[SC_SPEARSQUICKEN].timer!=-1 ) - skill_status_change_end(bl,SC_SPEARSQUICKEN,-1); - if(sc_data[SC_ADRENALINE].timer!=-1 ) - skill_status_change_end(bl,SC_ADRENALINE,-1); - if(sc_data[SC_LOUD].timer!=-1 ) - skill_status_change_end(bl,SC_LOUD,-1); - if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* ƒgƒDƒ‹?ƒTƒCƒg */ - skill_status_change_end(bl,SC_TRUESIGHT,-1); - if(sc_data[SC_WINDWALK].timer!=-1 ) /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ - skill_status_change_end(bl,SC_WINDWALK,-1); - if(sc_data[SC_CARTBOOST].timer!=-1 ) /* ƒJ?ƒgƒu?ƒXƒg */ - skill_status_change_end(bl,SC_CARTBOOST,-1); - break; - case SC_FLAMELAUNCHER: /* ƒtƒŒ?ƒ€ƒ‰ƒ“ƒ`ƒƒ? */ - skill_encchant_eremental_end(bl,SC_FLAMELAUNCHER); - break; - case SC_FROSTWEAPON: /* ƒtƒƒXƒgƒEƒFƒ|ƒ“ */ - skill_encchant_eremental_end(bl,SC_FROSTWEAPON); - break; - case SC_LIGHTNINGLOADER: /* ƒ‰ƒCƒgƒjƒ“ƒOƒ?ƒ_? */ - skill_encchant_eremental_end(bl,SC_LIGHTNINGLOADER); - break; - case SC_SEISMICWEAPON: /* ƒTƒCƒYƒ~ƒbƒNƒEƒFƒ|ƒ“ */ - skill_encchant_eremental_end(bl,SC_SEISMICWEAPON); - break; - case SC_DEVOTION: /* ƒfƒBƒ{?ƒVƒ‡ƒ“ */ - calc_flag = 1; - break; - case SC_PROVIDENCE: /* ƒvƒƒ”ƒBƒfƒ“ƒX */ - calc_flag = 1; - val2=val1*5; - break; - case SC_REFLECTSHIELD: - val2=10+val1*3; - break; - case SC_STRIPWEAPON: - case SC_STRIPSHIELD: - case SC_STRIPARMOR: - case SC_STRIPHELM: - case SC_CP_WEAPON: - case SC_CP_SHIELD: - case SC_CP_ARMOR: - case SC_CP_HELM: - break; - - case SC_AUTOSPELL: /* ƒI?ƒgƒXƒyƒ‹ */ - val4 = 5 + val1*2; - break; - - case SC_VOLCANO: - calc_flag = 1; - val3 = val1*10; - val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) ); - break; - case SC_DELUGE: - calc_flag = 1; - val3 = val1>=5?15: (val1==4?14: (val1==3?12: ( val1==2?9:5 ) ) ); - val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) ); - break; - case SC_VIOLENTGALE: - calc_flag = 1; - val3 = val1*3; - val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) ); - break; - - case SC_SPEARSQUICKEN: /* ƒXƒsƒAƒNƒCƒbƒPƒ“ */ - calc_flag = 1; - val2 = 20+val1; - *opt3 |= 1; - break; - case SC_COMBO: - break; - case SC_BLADESTOP_WAIT: /* ”’nŽæ‚è(‘Ò‚¿) */ - break; - case SC_BLADESTOP: /* ”’nŽæ‚è */ - if(val2==2) clif_bladestop((struct block_list *)val3,(struct block_list *)val4,1); - *opt3 |= 32; - break; - - case SC_LULLABY: /* ŽqŽç‰S */ - val2 = 11; - break; - case SC_RICHMANKIM: - break; - case SC_ETERNALCHAOS: /* ƒGƒ^?ƒiƒ‹ƒJƒIƒX */ - calc_flag = 1; - break; - case SC_DRUMBATTLE: /* ?‘¾ŒÛ‚Ì‹¿‚« */ - calc_flag = 1; - val2 = (val1+1)*25; - val3 = (val1+1)*2; - break; - case SC_NIBELUNGEN: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ - calc_flag = 1; - val2 = (val1+2)*50; - val3 = (val1+2)*25; - break; - case SC_ROKISWEIL: /* ƒƒL‚Ì‹©‚Ñ */ - break; - case SC_INTOABYSS: /* [•£‚Ì’†‚É */ - break; - case SC_SIEGFRIED: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ - calc_flag = 1; - val2 = 40 + val1*5; - val3 = val1*10; - break; - case SC_DISSONANCE: /* •s‹¦˜a‰¹ */ - val2 = 10; - break; - case SC_WHISTLE: /* Œû“J */ - calc_flag = 1; - break; - case SC_ASSNCROS: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX */ - calc_flag = 1; - break; - case SC_POEMBRAGI: /* ƒuƒ‰ƒM‚ÌŽ */ - break; - case SC_APPLEIDUN: /* ƒCƒhƒDƒ“‚Ì—ÑŒç */ - calc_flag = 1; - break; - case SC_UGLYDANCE: /* Ž©•ªŸŽè‚ȃ_ƒ“ƒX */ - val2 = 10; - break; - case SC_HUMMING: /* ƒnƒ~ƒ“ƒO */ - calc_flag = 1; - break; - case SC_DONTFORGETME: /* Ž„‚ð–Y‚ê‚È‚¢‚Å */ - calc_flag = 1; - if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* ‘¬“x㸉ðœ */ - skill_status_change_end(bl,SC_INCREASEAGI,-1); - if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 ) - skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1); - if(sc_data[SC_SPEARSQUICKEN].timer!=-1 ) - skill_status_change_end(bl,SC_SPEARSQUICKEN,-1); - if(sc_data[SC_ADRENALINE].timer!=-1 ) - skill_status_change_end(bl,SC_ADRENALINE,-1); - if(sc_data[SC_ASSNCROS].timer!=-1 ) - skill_status_change_end(bl,SC_ASSNCROS,-1); - if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* ƒgƒDƒ‹?ƒTƒCƒg */ - skill_status_change_end(bl,SC_TRUESIGHT,-1); - if(sc_data[SC_WINDWALK].timer!=-1 ) /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ - skill_status_change_end(bl,SC_WINDWALK,-1); - if(sc_data[SC_CARTBOOST].timer!=-1 ) /* ƒJ?ƒgƒu?ƒXƒg */ - skill_status_change_end(bl,SC_CARTBOOST,-1); - break; - case SC_FORTUNE: /* K‰^‚̃LƒX */ - calc_flag = 1; - break; - case SC_SERVICE4U: /* ƒT?ƒrƒXƒtƒH?ƒ†? */ - calc_flag = 1; - break; - case SC_DANCING: /* ƒ_ƒ“ƒX/‰‰‘t’† */ - calc_flag = 1; - val3= tick / 1000; - tick = 1000; - break; - - case SC_EXPLOSIONSPIRITS: // ”š—ô”g“® - calc_flag = 1; - val2 = 75 + 25*val1; - *opt3 |= 8; - break; - case SC_STEELBODY: // ‹à„ - calc_flag = 1; - *opt3 |= 16; - break; - case SC_EXTREMITYFIST: /* ˆ¢C—…”e™€Œ */ - break; - case SC_AUTOCOUNTER: - val3 = val4 = 0; - break; - - case SC_SPEEDPOTION0: /* ?‘¬ƒ|?ƒVƒ‡ƒ“ */ - case SC_SPEEDPOTION1: - case SC_SPEEDPOTION2: - calc_flag = 1; - tick = 1000 * tick; - val2 = 5*(2+type-SC_SPEEDPOTION0); - break; - - /* atk & matk potions [Valaris] */ - case SC_ATKPOT: - case SC_MATKPOT: - calc_flag = 1; - tick = 1000 * tick; - break; - case SC_WEDDING: //Œ‹¥—p(Œ‹¥ˆßւɂȂÁ‚Ä?‚‚Ì‚ª?‚¢‚Æ‚©) - { - time_t timer; - - calc_flag = 1; - tick = 10000; - if(!val2) - val2 = time(&timer); - } - break; - case SC_NOCHAT: //ƒ`ƒƒƒbƒg‹ÖŽ~?‘Ô - { - time_t timer; - - if(!battle_config.muting_players) - break; - - tick = 60000; - if(!val2) - val2 = time(&timer); - updateflag = SP_MANNER; - save_flag = 1; // celest - } - break; - case SC_SELFDESTRUCTION: //Ž©”š - clif_skillcasting(bl,bl->id, bl->id,0,0,331,skill_get_time(val2,val1)); - val3 = tick / 1000; - tick = 1000; - break; - - /* option1 */ - case SC_STONE: /* Ή» */ - if(!(flag&2)) { - int sc_def = battle_get_mdef(bl)*200; - tick = tick - sc_def; - } - val3 = tick/1000; - if(val3 < 1) val3 = 1; - tick = 5000; - val2 = 1; - break; - case SC_SLEEP: /* ‡–° */ - if(!(flag&2)) { -// int sc_def = 100 - (battle_get_int(bl) + battle_get_luk(bl)/3); -// tick = tick * sc_def / 100; -// if(tick < 1000) tick = 1000; - tick = 30000;//‡–°‚̓Xƒe?ƒ^ƒX‘Ï«‚É?‚í‚炸30•b - } - break; - case SC_FREEZE: /* “€Œ‹ */ - if(!(flag&2)) { - int sc_def = 100 - battle_get_mdef(bl); - tick = tick * sc_def / 100; - } - break; - case SC_STAN: /* ƒXƒ^ƒ“ival2‚Ƀ~ƒŠ•bƒZƒbƒgj */ - if(!(flag&2)) { - int sc_def = 100 - (battle_get_vit(bl) + battle_get_luk(bl)/3); - tick = tick * sc_def / 100; - } - break; - - /* option2 */ - case SC_POISON: /* “Å */ - case SC_DPOISON: /* –Ò“Å */ - calc_flag = 1; - if(!(flag&2)) { - int sc_def = 100 - (battle_get_vit(bl) + battle_get_luk(bl)/5); - tick = tick * sc_def / 100; - } - val3 = tick/1000; - if(val3 < 1) val3 = 1; - tick = 1000; - break; - case SC_SILENCE: /* ’¾?iƒŒƒbƒNƒXƒfƒr?ƒij */ - if(!(flag&2)) { - int sc_def = 100 - battle_get_vit(bl); - tick = tick * sc_def / 100; - } - break; - case SC_BLIND: /* ˆÃ? */ - calc_flag = 1; - if(!(flag&2)) { - int sc_def = battle_get_lv(bl)/10 + battle_get_int(bl)/15; - tick = 30000 - sc_def; - } - break; - case SC_CURSE: - calc_flag = 1; - if(!(flag&2)) { - int sc_def = 100 - battle_get_vit(bl); - tick = tick * sc_def / 100; - } - break; - - /* option */ - case SC_HIDING: /* ƒnƒCƒfƒBƒ“ƒO */ - calc_flag = 1; - if(bl->type == BL_PC) { - val2 = tick / 1000; /* Ž?ŽžŠÔ */ - tick = 1000; - } - break; - case SC_CHASEWALK: - case SC_CLOAKING: /* ƒNƒ?ƒLƒ“ƒO */ - if(bl->type == BL_PC) { - calc_flag = 1; // [Celest] - val2 = tick; - val3 = type==SC_CLOAKING ? 130-val1*3 : 135-val1*5; - } - else - tick = 5000*val1; - break; - case SC_SIGHT: /* ƒTƒCƒg/ƒ‹ƒAƒt */ - case SC_RUWACH: - val2 = tick/250; - tick = 10; - break; - - /* ƒZ?ƒtƒeƒBƒEƒH?ƒ‹Aƒjƒ…?ƒ} */ - case SC_SAFETYWALL: case SC_PNEUMA: - tick=((struct skill_unit *)val2)->group->limit; - break; - - /* ƒAƒ“ƒNƒ‹ */ - case SC_ANKLE: - break; - - /* ƒEƒH?ƒ^?ƒ{?ƒ‹ */ - case SC_WATERBALL: - tick=150; - if(val1>5) //ƒŒƒxƒ‹‚ª5ˆÈã‚ÌꇂÍ25?‚ɧŒÀ(1?–Ú‚Í‚·‚łɑłÁ‚Ä‚é‚Ì‚Å-1) - val3=5*5-1; - else - val3= (val1|1)*(val1|1)-1; - break; - - /* ƒXƒLƒ‹‚¶‚á‚È‚¢/ŽžŠÔ‚É?ŒW‚µ‚È‚¢ */ - case SC_RIDING: - calc_flag = 1; - tick = 600*1000; - break; - case SC_FALCON: - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_BROKNWEAPON: - case SC_BROKNARMOR: - tick=600*1000; - break; - - case SC_AUTOGUARD: - { - int i,t; - for(i=val2=0;i<val1;i++) { - t = 5-(i>>1); - val2 += (t < 0)? 1:t; - } - } - break; - - case SC_DEFENDER: - calc_flag = 1; - val2 = 5 + val1*15; - break; - - case SC_KEEPING: - case SC_BARRIER: - calc_flag = 1; - - case SC_HALLUCINATION: - break; - - case SC_CONCENTRATION: /* ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ */ - *opt3 |= 1; - calc_flag = 1; - break; - - case SC_TENSIONRELAX: /* ƒeƒ“ƒVƒ‡ƒ“ƒŠƒ‰ƒbƒNƒX */ - calc_flag = 1; - if(bl->type == BL_PC) { - tick = 10000; - } - break; - - case SC_AURABLADE: /* ƒI?ƒ‰ƒuƒŒ?ƒh */ - case SC_PARRYING: /* ƒpƒŠƒCƒ“ƒO */ -// case SC_ASSUMPTIO: /* */ - case SC_HEADCRUSH: /* ƒwƒbƒhƒNƒ‰ƒbƒVƒ… */ - case SC_JOINTBEAT: /* ƒWƒ‡ƒCƒ“ƒgƒr?ƒg */ -// case SC_MARIONETTE: /* ƒ}ƒŠƒIƒlƒbƒgƒRƒ“ƒgƒ?ƒ‹ */ - - //‚Æ‚è‚ ‚¦‚¸Žè?‚« - break; - -// -- moonsoul (for new upper class related skill status effects) -/* - case SC_AURABLADE: - val2 = val1*10; - break; - case SC_PARRYING: - val2=val1*3; - break; - case SC_CONCENTRATION: - calc_flag=1; - val2=val1*10; - val3=val1*5; - break; - case SC_TENSIONRELAX: -// val2 = 10; -// val3 = 15; - break; - case SC_BERSERK: - calc_flag=1; - break; - case SC_ASSUMPTIO: - if(sc_data[SC_KYRIE].timer!=-1 ) - skill_status_change_end(bl,SC_KYRIE,-1); - break; -*/ - case SC_WINDWALK: /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ - calc_flag = 1; - val2 = (val1 / 2); //Flee㸗¦ - break; - - case SC_BERSERK: /* ƒo?ƒT?ƒN */ - if(sd){ - sd->status.hp = sd->status.max_hp * 3; - sd->status.sp = 0; - clif_updatestatus(sd,SP_HP); - clif_updatestatus(sd,SP_SP); - clif_status_change(bl,SC_INCREASEAGI,1); /* ƒAƒCƒRƒ“•\ަ */ - } - *opt3 |= 128; - tick = 10000; - calc_flag = 1; - break; - - case SC_ASSUMPTIO: /* ƒAƒXƒ€ƒvƒeƒBƒI */ - *opt3 |= 2048; - break; - - case SC_BASILICA: // [celest] - break; - - case SC_MARIONETTE: /* ƒ}ƒŠƒIƒlƒbƒgƒRƒ“ƒgƒ?ƒ‹ */ - case SC_MARIONETTE2: - calc_flag = 1; - *opt3 |= 1024; - break; - - case SC_MELTDOWN: /* ƒƒ‹ƒgƒ_ƒEƒ“ */ - case SC_CARTBOOST: /* ƒJ?ƒgƒu?ƒXƒg */ - case SC_TRUESIGHT: /* ƒgƒDƒ‹?ƒTƒCƒg */ - case SC_SPIDERWEB: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ - case SC_MAGICPOWER: /* –‚–@—Í?• */ - calc_flag = 1; - break; - - case SC_REJECTSWORD: /* ƒŠƒWƒFƒNƒgƒ\?ƒh */ - val2 = 3; //3‰ñU?‚𒵂˕Ԃ· - break; - - case SC_MEMORIZE: /* ƒƒ‚ƒ‰ƒCƒY */ - val2 = 3; //3‰ñ‰r¥‚ð1/3‚É‚·‚é - break; - - case SC_GRAFFITI: /* ƒOƒ‰ƒtƒBƒeƒB */ - { - struct skill_unit_group *sg = skill_unitsetting(bl,RG_GRAFFITI,val1,val2,val3,0); - if(sg) - val4 = (int)sg; - } - break; - - case SC_SPLASHER: /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ? */ - break; - - case SC_FOGWALL: - val2 = 75; - // calc_flag = 1; // not sure of effects yet [celest] - break; - - case SC_BLOCKSKILL: - if (!tick) tick = 60000; - if (!val3) val3 = -1; - break; - - case SC_SLOWDOWN: - calc_flag = 1; - break; - - case SC_LEADERSHIP: - case SC_GLORYWOUNDS: - case SC_SOULCOLD: - case SC_HAWKEYES: - tick = 1000; - calc_flag = 1; - //val4 = 1; - break; - - case SC_REGENERATION: - val1 = 2; - case SC_BATTLEORDERS: - tick = 60000; // 1 minute - calc_flag = 1; - break; + nullpo_retr(1, bl); - default: - if(battle_config.error_log) - printf("UnknownStatusChange [%d]\n", type); + if (bl->type == BL_PC) { + nullpo_retr(1, sd = (struct map_session_data *)bl); + if (!battle_config.pc_cloak_check_type) // If it's No it shouldn't be checked return 0; - } - - if(bl->type==BL_PC && type<SC_SENDMAX) - clif_status_change(bl,type,1); /* ƒAƒCƒRƒ“•\ަ */ - - /* option‚Ì?X */ - switch(type){ - case SC_STONE: - case SC_FREEZE: - case SC_STAN: - case SC_SLEEP: - battle_stopattack(bl); /* U?’âŽ~ */ - skill_stop_dancing(bl,0); /* ‰‰‘t/ƒ_ƒ“ƒX‚Ì’†? */ - { /* “¯Žž‚ÉŠ|‚©‚ç‚È‚¢ƒXƒe?ƒ^ƒXˆÙí‚ð‰ðœ */ - int i; - for(i = SC_STONE; i <= SC_SLEEP; i++){ - if(sc_data[i].timer != -1){ - (*sc_count)--; - delete_timer(sc_data[i].timer, skill_status_change_timer); - sc_data[i].timer = -1; - } - } - } - if(type == SC_STONE) - *opt1 = 6; - else - *opt1 = type - SC_STONE + 1; - opt_flag = 1; - break; - case SC_POISON: - case SC_CURSE: - case SC_SILENCE: - case SC_BLIND: - *opt2 |= 1<<(type-SC_POISON); - opt_flag = 1; - break; - case SC_DPOISON: // Žb’肜ł̃GƒtƒFƒNƒg‚ðŽg—p - *opt2 |= 1; - opt_flag = 1; - break; - case SC_SIGNUMCRUCIS: - *opt2 |= 0x40; - opt_flag = 1; - break; - case SC_HIDING: - case SC_CLOAKING: - battle_stopattack(bl); /* U?’âŽ~ */ - *option |= ((type==SC_HIDING)?2:4); - opt_flag =1 ; - break; - case SC_CHASEWALK: - battle_stopattack(bl); /* U?’âŽ~ */ - *option |= 16388; - opt_flag =1 ; - break; - case SC_SIGHT: - *option |= 1; - opt_flag = 1; - break; - case SC_RUWACH: - *option |= 8192; - opt_flag = 1; - break; - case SC_WEDDING: - *option |= 4096; - opt_flag = 1; - } - - if(opt_flag) /* option‚Ì?X */ - clif_changeoption(bl); - - (*sc_count)++; /* ƒXƒe?ƒ^ƒXˆÙí‚Ì? */ - - sc_data[type].val1 = val1; - sc_data[type].val2 = val2; - sc_data[type].val3 = val3; - sc_data[type].val4 = val4; - /* ƒ^ƒCƒ}?Ý’è */ - sc_data[type].timer = add_timer( - gettick() + tick, skill_status_change_timer, bl->id, type); - - if(bl->type==BL_PC && calc_flag) - pc_calcstatus(sd,0); /* ƒXƒe?ƒ^ƒXÄŒvŽZ */ - - if(bl->type==BL_PC && save_flag) - chrif_save(sd); // save the player status - - if(bl->type==BL_PC && updateflag) - clif_updatestatus(sd,updateflag); /* ƒXƒe?ƒ^ƒX‚ðƒNƒ‰ƒCƒAƒ“ƒg‚É‘—‚é */ - - return 0; -} -/*========================================== - * ƒXƒe?ƒ^ƒXˆÙí‘S‰ðœ - *------------------------------------------ - */ -int skill_status_change_clear(struct block_list *bl, int type) -{ - struct status_change* sc_data; - short *sc_count, *option, *opt1, *opt2, *opt3; - int i; - - nullpo_retr(0, bl); - nullpo_retr(0, sc_data = battle_get_sc_data(bl)); - nullpo_retr(0, sc_count = battle_get_sc_count(bl)); - nullpo_retr(0, option = battle_get_option(bl)); - nullpo_retr(0, opt1 = battle_get_opt1(bl)); - nullpo_retr(0, opt2 = battle_get_opt2(bl)); - nullpo_retr(0, opt3 = battle_get_opt3(bl)); - - if (*sc_count == 0) + } else if (bl->type == BL_MOB && !battle_config.monster_cloak_check_type) return 0; - for(i = 0; i < MAX_STATUSCHANGE; i++){ - if(sc_data[i].timer != -1){ /* ˆÙ킪‚ ‚é‚È‚çƒ^ƒCƒ}?‚ð휂·‚é */ -/* - delete_timer(sc_data[i].timer, skill_status_change_timer); - sc_data[i].timer = -1; - - if (!type && i < SC_SENDMAX) - clif_status_change(bl, i, 0); -*/ - - skill_status_change_end(bl, i, -1); - } - } - *sc_count = 0; - *opt1 = 0; - *opt2 = 0; - *opt3 = 0; - *option &= OPTION_MASK; - - if (night_flag == 1 && type == BL_PC && !map[bl->m].flag.indoors && // by [Yor] - !map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) // [celest] - *opt2 |= STATE_BLIND; - if(!type || type&2) - clif_changeoption(bl); - - return 0; -} - -/* ƒNƒ?ƒLƒ“ƒO?¸iŽü‚è‚Ɉړ®•s‰Â”\’n?‚ª‚ ‚é‚©j */ -int skill_check_cloaking(struct block_list *bl) -{ - static int dx[]={ 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus - static int dy[]={-1, 0, 1, 0, -1, -1, 1, 1}; - int end=1,i; - - //missing sd [Found by Celest, commited by Aria] - struct map_session_data *sd=(struct map_session_data *)bl; - - nullpo_retr(0, bl); - - if(bl->type == BL_PC && !battle_config.pc_cloak_check_type) // If it's No it shouldn't be checked - return 0; - else if(bl->type == BL_MOB && !battle_config.monster_cloak_check_type) - return 0; - for(i=0;i<sizeof(dx)/sizeof(dx[0]);i++){ - int c=map_getcell(bl->m,bl->x+dx[i],bl->y+dy[i]); - if(c==1 || c==5) { - end=0; + for (i = 0; i < 8; i++) { + if (map_getcell(bl->m, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS)) { + end = 0; break; } } if(end){ - if ((bl->type == BL_PC && pc_checkskill(sd,AS_CLOAKING)<3) || bl->type == BL_MOB) { - skill_status_change_end(bl, SC_CLOAKING, -1); - *battle_get_option(bl)&=~4; /* ”O‚Ì‚½‚ß‚Ì?— */ + if ((sd && pc_checkskill(sd,AS_CLOAKING)<3) || bl->type == BL_MOB) { + status_change_end(bl, SC_CLOAKING, -1); } - else if (bl->type == BL_PC && sd->sc_data[SC_CLOAKING].val3 != 130) { + else if (sd && sd->sc_data[SC_CLOAKING].val3 != 130) { sd->sc_data[SC_CLOAKING].val3 = 130; - pc_calcspeed (sd); + status_calc_speed (sd); } } else { - if (bl->type == BL_PC && sd->sc_data[SC_CLOAKING].val3 != 103) { + if (sd && sd->sc_data[SC_CLOAKING].val3 != 103) { sd->sc_data[SC_CLOAKING].val3 = 103; - pc_calcspeed (sd); + status_calc_speed (sd); } } - return end; -} -int skill_type_cloaking(struct block_list *bl) -{ - static int dx[]={ 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus - static int dy[]={-1, 0, 1, 0, -1, -1, 1, 1}; - int i; - - nullpo_retr(0, bl); - if(bl->type == BL_PC && battle_config.pc_cloak_check_type&1) - return 0; - else if(bl->type == BL_MOB && battle_config.monster_cloak_check_type&1) - return 0; - for(i=0; i<sizeof(dx)/sizeof(dx[0]); i++) - { - int c=map_getcell(bl->m,bl->x+dx[i],bl->y+dy[i]); - if(c==1 || c==5) - return 0; - } - return 1; + return end; } /* @@ -10018,48 +8096,6 @@ int skill_type_cloaking(struct block_list *bl) */ /*========================================== - * ‰‰‘t/ƒ_ƒ“ƒXƒXƒLƒ‹‚©‚Ç‚¤‚©”»’è - * ˆø? ƒXƒLƒ‹ID - * ?‚è ƒ_ƒ“ƒX‚¶‚á‚È‚¢=0 ‡‘t=2 ‚»‚êˆÈŠO‚̃_ƒ“ƒX=1 - *------------------------------------------ - */ -int skill_is_danceskill(int id) -{ - int i; - switch(id){ - case BD_LULLABY: /* ŽqŽç‰Ì */ - case BD_RICHMANKIM: /* ƒjƒˆƒ‹ƒh‚̉ƒ */ - case BD_ETERNALCHAOS: /* ‰i‰“‚̬“× */ - case BD_DRUMBATTLEFIELD: /* ?‘¾ŒÛ‚Ì‹¿‚« */ - case BD_RINGNIBELUNGEN: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ - case BD_ROKISWEIL: /* ƒƒL‚Ì‹©‚Ñ */ - case BD_INTOABYSS: /* [•£‚Ì’†‚É */ - case BD_SIEGFRIED: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ - case BD_RAGNAROK: /* _?‚Ì?¨ */ - case CG_MOONLIT: /* ŒŽ–¾‚è‚Ìò‚É—Ž‚¿‚é‰Ô‚Ñ‚ç */ - i=2; - break; - case BA_DISSONANCE: /* •s‹¦˜a‰¹ */ - case BA_FROSTJOKE: /* Ц‚¢ƒWƒ‡?ƒN */ - case BA_WHISTLE: /* Œû“J */ - case BA_ASSASSINCROSS: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX */ - case BA_POEMBRAGI: /* ƒuƒ‰ƒM‚ÌŽ */ - case BA_APPLEIDUN: /* ƒCƒhƒDƒ“‚Ì—ÑŒç */ - case DC_UGLYDANCE: /* Ž©•ªŸŽè‚ȃ_ƒ“ƒX */ - case DC_SCREAM: /* ƒXƒNƒŠ?ƒ€ */ - case DC_HUMMING: /* ƒnƒ~ƒ“ƒO */ - case DC_DONTFORGETME: /* Ž„‚ð–Y‚ê‚È‚¢‚Åc */ - case DC_FORTUNEKISS: /* K‰^‚̃LƒX */ - case DC_SERVICEFORYOU: /* ƒT?ƒrƒXƒtƒH?ƒ†? */ - i=1; - break; - default: - i=0; - } - return i; -} - -/*========================================== * ‰‰‘t/ƒ_ƒ“ƒX‚ð‚â‚ß‚é * flag 1‚Ň‘t’†‚Ȃ瑊•û‚Ƀ†ƒjƒbƒg‚ð”C‚¹‚é * @@ -10069,47 +8105,47 @@ void skill_stop_dancing(struct block_list *src, int flag) { struct status_change* sc_data; struct skill_unit_group* group; + short* sc_count; nullpo_retv(src); - - sc_data=battle_get_sc_data(src); - if(sc_data && sc_data[SC_DANCING].timer != -1) { - group=(struct skill_unit_group *)sc_data[SC_DANCING].val2; //ƒ_ƒ“ƒX‚̃XƒLƒ‹ƒ†ƒjƒbƒgID‚Íval2‚É“ü‚Á‚Ä‚é - if(group && src->type==BL_PC && sc_data && sc_data[SC_DANCING].val4){ //‡‘t’†? - struct map_session_data* dsd=map_id2sd(sc_data[SC_DANCING].val4); //‘Š•û‚ÌsdŽæ“¾ - if(flag){ //ƒƒOƒAƒEƒg‚ȂǕЕû‚ª—Ž‚¿‚Ä‚à‰‰‘t‚ª??‚³‚ê‚é - if(dsd && src->id == group->src_id){ //ƒOƒ‹?ƒv‚ðŽ‚Á‚Ä‚éPC‚ª—Ž‚¿‚é - group->src_id=sc_data[SC_DANCING].val4; //‘Š•û‚ɃOƒ‹?ƒv‚ð”C‚¹‚é - if(flag&1) //ƒƒOƒAƒEƒg - dsd->sc_data[SC_DANCING].val4=0; //‘Š•û‚Ì‘Š•û‚ð0‚É‚µ‚ć‘tI—¹¨’Êí‚̃_ƒ“ƒX?‘Ô - if(flag&2) //ƒnƒG”ò‚Ñ‚È‚Ç - return; //‡‘t‚àƒ_ƒ“ƒX?‘Ô‚àI—¹‚³‚¹‚È‚¢•ƒXƒLƒ‹ƒ†ƒjƒbƒg‚Í’u‚¢‚Ä‚¯‚Ú‚è - }else if(dsd && dsd->bl.id == group->src_id){ //‘Š•û‚ªƒOƒ‹?ƒv‚ðŽ‚Á‚Ä‚¢‚éPC‚ª—Ž‚¿‚é(Ž©•ª‚̓Oƒ‹?ƒv‚ðŽ‚Á‚Ä‚¢‚È‚¢) - if(flag&1) //ƒƒOƒAƒEƒg - dsd->sc_data[SC_DANCING].val4=0; //‘Š•û‚Ì‘Š•û‚ð0‚É‚µ‚ć‘tI—¹¨’Êí‚̃_ƒ“ƒX?‘Ô - if(flag&2) //ƒnƒG”ò‚Ñ‚È‚Ç - return; //‡‘t‚àƒ_ƒ“ƒX?‘Ô‚àI—¹‚³‚¹‚È‚¢•ƒXƒLƒ‹ƒ†ƒjƒbƒg‚Í’u‚¢‚Ä‚¯‚Ú‚è + nullpo_retv(sc_data = status_get_sc_data(src)); + nullpo_retv(sc_count = status_get_sc_count(src)); + + if((*sc_count) > 0 && sc_data[SC_DANCING].timer != -1) { + group = (struct skill_unit_group *)sc_data[SC_DANCING].val2; //ƒ_ƒ“ƒX‚̃XƒLƒ‹ƒ†ƒjƒbƒgID‚Íval2‚É“ü‚Á‚Ä‚é + if (src->type == BL_PC) { + if (group && sc_data[SC_DANCING].val4){ //‡‘t’†? + struct map_session_data* dsd = map_id2sd(sc_data[SC_DANCING].val4); //‘Š•û‚ÌsdŽæ“¾ + if (flag && dsd) { //ƒƒOƒAƒEƒg‚ȂǕЕû‚ª—Ž‚¿‚Ä‚à‰‰‘t‚ª??‚³‚ê‚é + if (src->id == group->src_id) { //ƒOƒ‹?ƒv‚ðŽ‚Á‚Ä‚éPC‚ª—Ž‚¿‚é + group->src_id = sc_data[SC_DANCING].val4; //‘Š•û‚ɃOƒ‹?ƒv‚ð”C‚¹‚é + if (flag & 1) //ƒƒOƒAƒEƒg + dsd->sc_data[SC_DANCING].val4 = 0; //‘Š•û‚Ì‘Š•û‚ð0‚É‚µ‚ć‘tI—¹¨’Êí‚̃_ƒ“ƒX?‘Ô + if(flag & 2) //ƒnƒG”ò‚Ñ‚È‚Ç + return; //‡‘t‚àƒ_ƒ“ƒX?‘Ô‚àI—¹‚³‚¹‚È‚¢•ƒXƒLƒ‹ƒ†ƒjƒbƒg‚Í’u‚¢‚Ä‚¯‚Ú‚è + } else if (dsd->bl.id == group->src_id) { //‘Š•û‚ªƒOƒ‹?ƒv‚ðŽ‚Á‚Ä‚¢‚éPC‚ª—Ž‚¿‚é(Ž©•ª‚̓Oƒ‹?ƒv‚ðŽ‚Á‚Ä‚¢‚È‚¢) + if (flag & 1) //ƒƒOƒAƒEƒg + dsd->sc_data[SC_DANCING].val4 = 0; //‘Š•û‚Ì‘Š•û‚ð0‚É‚µ‚ć‘tI—¹¨’Êí‚̃_ƒ“ƒX?‘Ô + if(flag & 2) //ƒnƒG”ò‚Ñ‚È‚Ç + return; //‡‘t‚àƒ_ƒ“ƒX?‘Ô‚àI—¹‚³‚¹‚È‚¢•ƒXƒLƒ‹ƒ†ƒjƒbƒg‚Í’u‚¢‚Ä‚¯‚Ú‚è + } + status_change_end(src, SC_DANCING, -1); //Ž©•ª‚̃Xƒe?ƒ^ƒX‚ðI—¹‚³‚¹‚é + //‚»‚µ‚ăOƒ‹?ƒv‚ÍÁ‚³‚È‚¢•Á‚³‚È‚¢‚̂ŃXƒe?ƒ^ƒXŒvŽZ‚à‚¢‚ç‚È‚¢H + return; + } else if (dsd) { + if (src->id == group->src_id) //ƒOƒ‹?ƒv‚ðŽ‚Á‚Ä‚éPC‚ªŽ~‚ß‚é + status_change_end(&dsd->bl, SC_DANCING, -1); //‘ŠŽè‚̃Xƒe?ƒ^ƒX‚ðI—¹‚³‚¹‚é + if(dsd->bl.id == group->src_id) //‘Š•û‚ªƒOƒ‹?ƒv‚ðŽ‚Á‚Ä‚¢‚éPC‚ªŽ~‚ß‚é(Ž©•ª‚̓Oƒ‹?ƒv‚ðŽ‚Á‚Ä‚¢‚È‚¢) + status_change_end(src, SC_DANCING, -1); //Ž©•ª‚̃Xƒe?ƒ^ƒX‚ðI—¹‚³‚¹‚é } - skill_status_change_end(src,SC_DANCING,-1);//Ž©•ª‚̃Xƒe?ƒ^ƒX‚ðI—¹‚³‚¹‚é - //‚»‚µ‚ăOƒ‹?ƒv‚ÍÁ‚³‚È‚¢•Á‚³‚È‚¢‚̂ŃXƒe?ƒ^ƒXŒvŽZ‚à‚¢‚ç‚È‚¢H + } + if(flag & 2 && group) { //ƒnƒG‚Å”ò‚ñ‚¾‚Æ‚«‚Æ‚©‚̓†ƒjƒbƒg‚à”ò‚Ô + struct map_session_data *sd = (struct map_session_data *)src; + if (sd) skill_unit_move_unit_group(group, sd->bl.m, (sd->to_x - sd->bl.x), (sd->to_y - sd->bl.y)); return; - }else{ - if(dsd && src->id == group->src_id){ //ƒOƒ‹?ƒv‚ðŽ‚Á‚Ä‚éPC‚ªŽ~‚ß‚é - skill_status_change_end((struct block_list *)dsd,SC_DANCING,-1);//‘ŠŽè‚̃Xƒe?ƒ^ƒX‚ðI—¹‚³‚¹‚é - } - if(dsd && dsd->bl.id == group->src_id){ //‘Š•û‚ªƒOƒ‹?ƒv‚ðŽ‚Á‚Ä‚¢‚éPC‚ªŽ~‚ß‚é(Ž©•ª‚̓Oƒ‹?ƒv‚ðŽ‚Á‚Ä‚¢‚È‚¢) - skill_status_change_end(src,SC_DANCING,-1);//Ž©•ª‚̃Xƒe?ƒ^ƒX‚ðI—¹‚³‚¹‚é - } } } - if(flag&2 && group && src->type==BL_PC){ //ƒnƒG‚Å”ò‚ñ‚¾‚Æ‚«‚Æ‚©‚̓†ƒjƒbƒg‚à”ò‚Ô - struct map_session_data *sd = (struct map_session_data *)src; - skill_unit_move_unit_group(group, sd->bl.m,(sd->to_x - sd->bl.x),(sd->to_y - sd->bl.y)); - return; - } skill_delunitgroup(group); - if(src->type==BL_PC) - pc_calcstatus((struct map_session_data *)src,0); } } @@ -10138,10 +8174,13 @@ struct skill_unit *skill_initunit(struct skill_unit_group *group,int idx,int x,i map_addblock(&unit->bl); clif_skill_setunit(unit); + + if (group->skill_id==HP_BASILICA) + skill_basilica_cell(unit,CELL_SETBASILICA); + return unit; } -int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap ); /*========================================== * ƒXƒLƒ‹ƒ†ƒjƒbƒgíœ *------------------------------------------ @@ -10149,7 +8188,6 @@ int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap ); int skill_delunit(struct skill_unit *unit) { struct skill_unit_group *group; - int range; nullpo_retr(0, unit); if(!unit->alive) @@ -10159,11 +8197,15 @@ int skill_delunit(struct skill_unit *unit) /* onlimitƒCƒxƒ“ƒgŒÄ‚Ño‚µ */ skill_unit_onlimit( unit,gettick() ); - /* ondeleteƒCƒxƒ“ƒgŒÄ‚Ño‚µ */ - range=group->range; - map_foreachinarea( skill_unit_timer_sub_ondelete, unit->bl.m, - unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0, - &unit->bl,gettick() ); + /* onoutƒCƒxƒ“ƒgŒÄ‚Ño‚µ */ + if (!unit->range) { + map_foreachinarea(skill_unit_effect,unit->bl.m, + unit->bl.x,unit->bl.y,unit->bl.x,unit->bl.y,0, + &unit->bl,gettick(),0); + } + + if (group->skill_id==HP_BASILICA) + skill_basilica_cell(unit,CELL_CLRBASILICA); clif_skill_delunit(unit); @@ -10179,7 +8221,7 @@ int skill_delunit(struct skill_unit *unit) * ƒXƒLƒ‹ƒ†ƒjƒbƒgƒOƒ‹?ƒv‰Šú‰» *------------------------------------------ */ -static int skill_unit_group_newid=10; +static int skill_unit_group_newid = MAX_SKILL_DB; struct skill_unit_group *skill_initunitgroup(struct block_list *src, int count,int skillid,int skilllv,int unit_id) { @@ -10227,11 +8269,11 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src, } group->src_id=src->id; - group->party_id=battle_get_party_id(src); - group->guild_id=battle_get_guild_id(src); + group->party_id=status_get_party_id(src); + group->guild_id=status_get_guild_id(src); group->group_id=skill_unit_group_newid++; if(skill_unit_group_newid<=0) - skill_unit_group_newid=10; + skill_unit_group_newid = MAX_SKILL_DB; group->unit=(struct skill_unit *)aCalloc(count,sizeof(struct skill_unit)); group->unit_count=count; group->val1=group->val2=0; @@ -10239,39 +8281,23 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src, group->skill_lv=skilllv; group->unit_id=unit_id; group->map=src->m; - group->range=0; group->limit=10000; group->interval=1000; group->tick=gettick(); group->valstr=NULL; - if( skill_is_danceskill(skillid) ){ + if (skill_get_unit_flag(skillid)&UF_DANCE) { struct map_session_data *sd = NULL; if(src->type==BL_PC && (sd=(struct map_session_data *)src) ){ sd->skillid_dance=skillid; sd->skilllv_dance=skilllv; } - skill_status_change_start(src,SC_DANCING,skillid,(int)group,0,0,skill_get_time(skillid,skilllv)+1000,0); - switch(skillid){ //‡‘tƒXƒLƒ‹‚Í‘Š•û‚ðƒ_ƒ“ƒX?‘Ô‚É‚·‚é - case BD_LULLABY: /* ŽqŽç‰Ì */ - case BD_RICHMANKIM: /* ƒjƒˆƒ‹ƒh‚̉ƒ */ - case BD_ETERNALCHAOS: /* ‰i‰“‚̬“× */ - case BD_DRUMBATTLEFIELD: /* ?‘¾ŒÛ‚Ì‹¿‚« */ - case BD_RINGNIBELUNGEN: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ - case BD_ROKISWEIL: /* ƒƒL‚Ì‹©‚Ñ */ - case BD_INTOABYSS: /* [•£‚Ì’†‚É */ - case BD_SIEGFRIED: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ - case BD_RAGNAROK: /* _?‚Ì?¨ */ - case CG_MOONLIT: /* ŒŽ–¾‚è‚Ìò‚É—Ž‚¿‚é‰Ô‚Ñ‚ç */ - { - int range=1; - int c=0; - if(sd){ - map_foreachinarea(skill_check_condition_use_sub,sd->bl.m, - sd->bl.x-range,sd->bl.y-range, - sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c); - } - } + status_change_start(src,SC_DANCING,skillid,(int)group,0,0,skill_get_time(skillid,skilllv)+1000,0); + //‡‘tƒXƒLƒ‹‚Í‘Š•û‚ðƒ_ƒ“ƒXó‘Ô‚É‚·‚é + if (sd && skill_get_unit_flag(skillid)&UF_ENSEMBLE) { + int c=0; + map_foreachinarea(skill_check_condition_use_sub,sd->bl.m, + sd->bl.x-1,sd->bl.y-1,sd->bl.x+1,sd->bl.y+1,BL_PC,&sd->bl,&c); } } return group; @@ -10291,10 +8317,16 @@ int skill_delunitgroup(struct skill_unit_group *group) return 0; src=map_id2bl(group->src_id); - if( skill_is_danceskill(group->skill_id) ){ //ƒ_ƒ“ƒXƒXƒLƒ‹‚̓_ƒ“ƒX?‘Ô‚ð‰ðœ‚·‚é - if(src) - skill_status_change_end(src,SC_DANCING,-1); + //ƒ_ƒ“ƒXƒXƒLƒ‹‚̓_ƒ“ƒXó‘Ô‚ð‰ðœ‚·‚é + if(src) { + if (skill_get_unit_flag(group->skill_id)&UF_DANCE) + status_change_end(src,SC_DANCING,-1); + if (group->unit_id == 0x86) { + struct status_change *sc_data = status_get_sc_data(src); + if(sc_data && sc_data[SC_MAGICPOWER].timer != -1) //ƒ}ƒWƒbƒNƒpƒ?‚Ì?‰ÊI—¹ + status_change_end(src,SC_MAGICPOWER,-1); } + } group->alive_count=0; if(group->unit!=NULL){ @@ -10307,7 +8339,7 @@ int skill_delunitgroup(struct skill_unit_group *group) group->valstr=NULL; } - map_freeblock(group->unit); /* free()‚̑ւí‚è */ + map_freeblock(group->unit); /* aFree()‚̑ւí‚è */ group->unit=NULL; group->src_id=0; group->group_id=0; @@ -10329,13 +8361,14 @@ int skill_clear_unitgroup(struct block_list *src) if(src->type==BL_PC){ group=((struct map_session_data *)src)->skillunit; maxsug=MAX_SKILLUNITGROUP; - }else if(src->type==BL_MOB){ + } else if(src->type==BL_MOB){ group=((struct mob_data *)src)->skillunit; maxsug=MAX_MOBSKILLUNITGROUP; - }else if(src->type==BL_PET){ // [Valaris] + } else if(src->type==BL_PET){ // [Valaris] group=((struct pet_data *)src)->skillunit; maxsug=MAX_MOBSKILLUNITGROUP; - } + } else + return 0; if(group){ int i; for(i=0;i<maxsug;i++) @@ -10350,54 +8383,46 @@ int skill_clear_unitgroup(struct block_list *src) *------------------------------------------ */ struct skill_unit_group_tickset *skill_unitgrouptickset_search( - struct block_list *bl,int group_id) + struct block_list *bl,struct skill_unit_group *group,int tick) { - int i,j=0,k,s=group_id%MAX_SKILLUNITGROUPTICKSET; - struct skill_unit_group_tickset *set=NULL; + int i,j=-1,k,s,id; + struct skill_unit_group_tickset *set; nullpo_retr(0, bl); + if (group->interval==-1) + return NULL; - if(bl->type==BL_PC){ - set=((struct map_session_data *)bl)->skillunittick; - }else{ - set=((struct mob_data *)bl)->skillunittick; - } - if(set==NULL) + if (bl->type == BL_PC) + set = ((struct map_session_data *)bl)->skillunittick; + else if (bl->type == BL_MOB) + set = ((struct mob_data *)bl)->skillunittick; + else return 0; - for(i=0;i<MAX_SKILLUNITGROUPTICKSET;i++) - if( set[(k=(i+s)%MAX_SKILLUNITGROUPTICKSET)].group_id == group_id ) - return &set[k]; - else if( set[k].group_id==0 ) - j=k; - return &set[j]; -} - -/*========================================== - * ƒXƒLƒ‹ƒ†ƒjƒbƒgƒOƒ‹?ƒv‚Ì”í‰e‹¿tickíœ - *------------------------------------------ - */ -int skill_unitgrouptickset_delete(struct block_list *bl,int group_id) -{ - int i,s=group_id%MAX_SKILLUNITGROUPTICKSET; - struct skill_unit_group_tickset *set=NULL,*ts; - - nullpo_retr(0, bl); + if (skill_get_unit_flag(group->skill_id)&UF_NOOVERLAP) + id = s = group->skill_id; + else + id = s = group->group_id; - if(bl->type==BL_PC){ - set=((struct map_session_data *)bl)->skillunittick; - }else{ - set=((struct mob_data *)bl)->skillunittick; + for (i=0; i<MAX_SKILLUNITGROUPTICKSET; i++) { + k = (i+s) % MAX_SKILLUNITGROUPTICKSET; + if (set[k].id == id) + return &set[k]; + else if (j==-1 && (DIFF_TICK(tick,set[k].tick)>0 || set[k].id==0)) + j=k; } - if(set!=NULL){ - - for(i=0;i<MAX_SKILLUNITGROUPTICKSET;i++) - if( (ts=&set[(i+s)%MAX_SKILLUNITGROUPTICKSET])->group_id == group_id ) - ts->group_id=0; - + if (j == -1) { + if(battle_config.error_log) { + sprintf (tmp_output, "skill_unitgrouptickset_search: tickset is full\n"); + ShowWarning (tmp_output); + } + j = id % MAX_SKILLUNITGROUPTICKSET; } - return 0; + + set[j].id = id; + set[j].tick = tick; + return &set[j]; } /*========================================== @@ -10406,49 +8431,27 @@ int skill_unitgrouptickset_delete(struct block_list *bl,int group_id) */ int skill_unit_timer_sub_onplace( struct block_list *bl, va_list ap ) { - struct block_list *src; - struct skill_unit *su; + struct skill_unit *unit; + struct skill_unit_group *group; unsigned int tick; nullpo_retr(0, bl); nullpo_retr(0, ap); - src=va_arg(ap,struct block_list*); - - tick=va_arg(ap,unsigned int); - su = (struct skill_unit *)src; + unit = va_arg(ap,struct skill_unit *); + tick = va_arg(ap,unsigned int); - if( su && su->alive ) { - struct skill_unit_group *sg; - sg = su->group; - if(sg && battle_check_target(src,bl,sg->target_flag )>0) - skill_unit_onplace( su, bl, tick ); - } - return 0; -} + if (bl->type!=BL_PC && bl->type!=BL_MOB) + return 0; + if (!unit->alive || bl->prev==NULL) + return 0; -/*========================================== - * ƒXƒLƒ‹ƒ†ƒjƒbƒgƒ^ƒCƒ}?íœ?——p(foreachinarea) - *------------------------------------------ - */ -int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap ) -{ - struct block_list *src; - struct skill_unit *su; - unsigned int tick; + nullpo_retr(0, group=unit->group); - nullpo_retr(0, bl); - nullpo_retr(0, ap); - src=va_arg(ap,struct block_list*); + if (battle_check_target(&unit->bl,bl,group->target_flag)<=0) + return 0; - tick=va_arg(ap,unsigned int); - su = (struct skill_unit *)src; + skill_unit_onplace_timer(unit,bl,tick); - if( su && su->alive ){ - struct skill_unit_group *sg; - sg = su->group; - if( sg && battle_check_target(src,bl,sg->target_flag )>0 ) - skill_unit_ondelete( su, bl, tick ); - } return 0; } @@ -10466,28 +8469,38 @@ int skill_unit_timer_sub( struct block_list *bl, va_list ap ) nullpo_retr(0, bl); nullpo_retr(0, ap); nullpo_retr(0, unit=(struct skill_unit *)bl); - nullpo_retr(0, group=unit->group); tick=va_arg(ap,unsigned int); if(!unit->alive) return 0; + group=unit->group; - range=(unit->range!=0)?unit->range:group->range; + nullpo_retr(0, group); + range = unit->range; - /* onplaceƒCƒxƒ“ƒgŒÄ‚Ño‚µ */ - if(unit->alive && unit->range>=0){ - map_foreachinarea( skill_unit_timer_sub_onplace, bl->m, - bl->x-range,bl->y-range,bl->x+range,bl->y+range,0, - bl,tick); - if(group->unit_id == 0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val2){ - map_foreachinarea( skill_idun_heal, bl->m, - bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,unit); - group->val2++; + /* onplace_timerƒCƒxƒ“ƒgŒÄ‚Ño‚µ */ + if (range>=0 && group->interval!=-1) { + map_foreachinarea(skill_unit_timer_sub_onplace, bl->m, + bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,bl,tick); + if (!unit->alive) + return 0; + // ƒ}ƒOƒkƒX‚Í”“®‚µ‚½ƒ†ƒjƒbƒg‚Í휂·‚é + if (group->skill_id==PR_MAGNUS && unit->val2) { + skill_delunit(unit); + return 0; } } + // ƒCƒhƒDƒ“‚Ì—ÑŒç‚É‚æ‚é‰ñ•œ + if (group->unit_id==0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val3) { + struct block_list *src = map_id2bl(group->src_id); + int range = skill_get_unit_layout_type(group->skill_id,group->skill_lv); + nullpo_retr(0, src); + map_foreachinarea(skill_idun_heal,src->m, + src->x-range,src->y-range,src->x+range,src->y+range,0,unit); + group->val3++; + } /* ŽžŠÔØ‚êíœ */ - if(unit->alive && - (DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit) ){ + if((DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit)){ switch(group->unit_id){ case 0x8f: /* ƒuƒ‰ƒXƒgƒ}ƒCƒ“ */ group->unit_id = 0x8c; @@ -10516,7 +8529,21 @@ int skill_unit_timer_sub( struct block_list *bl, va_list ap ) map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,NULL,NULL,NULL,0); // ?•ÔŠÒ } } + skill_delunit(unit); } + break; + + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc4: + { + struct block_list *src=map_id2bl(group->src_id); + if (src) + group->tick = tick; + } + break; + default: skill_delunit(unit); } @@ -10549,92 +8576,33 @@ int skill_unit_timer( int tid,unsigned int tick,int id,int data) * ƒXƒLƒ‹ƒ†ƒjƒbƒgˆÚ“®Žž?——p(foreachinarea) *------------------------------------------ */ -int skill_unit_out_all_sub( struct block_list *bl, va_list ap ) -{ - struct skill_unit *unit; - struct skill_unit_group *group; - struct block_list *src; - int range; - unsigned int tick; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - nullpo_retr(0, unit=(struct skill_unit *)bl); - nullpo_retr(0, group=unit->group); - - tick=va_arg(ap,unsigned int); - - if(!unit->alive || src->prev==NULL) - return 0; - - range=(unit->range!=0)?unit->range:group->range; - - if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 ) - return 0; - - if( src->x >= bl->x-range && src->x <= bl->x+range && - src->y >= bl->y-range && src->y <= bl->y+range ) - skill_unit_onout( unit, src, tick ); - - return 0; -} - - -/*========================================== - * ƒXƒLƒ‹ƒ†ƒjƒbƒgˆÚ“®Žž?— - *------------------------------------------ - */ -int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range) -{ - nullpo_retr(0, bl); - - if( bl->prev==NULL ) - return 0; - - if(range<7) - range=7; - map_foreachinarea( skill_unit_out_all_sub, - bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL, - bl,tick ); - - return 0; -} - -/*========================================== - * ƒXƒLƒ‹ƒ†ƒjƒbƒgˆÚ“®Žž?——p(foreachinarea) - *------------------------------------------ - */ int skill_unit_move_sub( struct block_list *bl, va_list ap ) { - struct skill_unit *unit; + struct skill_unit *unit = (struct skill_unit *)bl; struct skill_unit_group *group; - struct block_list *src; - int range; - unsigned int tick; + struct block_list *target; + unsigned int tick,flag; nullpo_retr(0, bl); nullpo_retr(0, ap); - nullpo_retr(0, unit=(struct skill_unit *)bl); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - - tick=va_arg(ap,unsigned int); + nullpo_retr(0, target=va_arg(ap,struct block_list*)); + tick = va_arg(ap,unsigned int); + flag = va_arg(ap,int); - if(!unit->alive || src->prev==NULL) + if (target->type!=BL_PC && target->type!=BL_MOB) return 0; - if((group=unit->group) == NULL) + nullpo_retr(0, group=unit->group); + if (group->interval!=-1) return 0; - range=(unit->range!=0)?unit->range:group->range; - if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 ) + if (!unit->alive || target->prev==NULL) return 0; - if( src->x >= bl->x-range && src->x <= bl->x+range && - src->y >= bl->y-range && src->y <= bl->y+range ) - skill_unit_onplace( unit, src, tick ); + if (flag) + skill_unit_onplace(unit,target,tick); else - skill_unit_onout( unit, src, tick ); + skill_unit_onout(unit,target,tick); return 0; } @@ -10643,173 +8611,117 @@ int skill_unit_move_sub( struct block_list *bl, va_list ap ) * ƒXƒLƒ‹ƒ†ƒjƒbƒgˆÚ“®Žž?— *------------------------------------------ */ -int skill_unit_move( struct block_list *bl,unsigned int tick,int range) +int skill_unit_move(struct block_list *bl,unsigned int tick,int flag) { nullpo_retr(0, bl); - if( bl->prev==NULL ) + if(bl->prev==NULL ) return 0; - if(range<7) - range=7; - map_foreachinarea( skill_unit_move_sub, - bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL, - bl,tick ); + map_foreachinarea(skill_unit_move_sub, + bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,bl,tick,flag); return 0; } /*========================================== - * ƒXƒLƒ‹ƒ†ƒjƒbƒgŽ©?‚̈ړ®Žž?—(foreachinarea) - *------------------------------------------ - */ -int skill_unit_move_unit_group_sub( struct block_list *bl, va_list ap ) -{ - struct skill_unit *unit; - struct skill_unit_group *group; - struct block_list *src; - int range; - unsigned int tick; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - nullpo_retr(0, unit=(struct skill_unit *)src); - nullpo_retr(0, group=unit->group); - - tick=va_arg(ap,unsigned int); - - if(!unit->alive || bl->prev==NULL) - return 0; - - range=(unit->range!=0)?unit->range:group->range; - - if( range<0 || battle_check_target(src,bl,group->target_flag )<=0 ) - return 0; - if( bl->x >= src->x-range && bl->x <= src->x+range && - bl->y >= src->y-range && bl->y <= src->y+range ) - skill_unit_onplace( unit, bl, tick ); - else - skill_unit_onout( unit, bl, tick ); - return 0; -} - -/*========================================== * ƒXƒLƒ‹ƒ†ƒjƒbƒgŽ©?‚̈ړ®Žž?— * ˆø?‚̓Oƒ‹?ƒv‚ƈړ®—Ê *------------------------------------------ */ int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy) { + int i,j; + int tick = gettick(); + int *m_flag; + struct skill_unit *unit1; + struct skill_unit *unit2; + nullpo_retr(0, group); + if (group->unit_count<=0) + return 0; + if (group->unit==NULL) + return 0; - if( group->unit_count<=0) + // ˆÚ“®‰Â”\‚ȃXƒLƒ‹‚̓_ƒ“ƒXŒn‚ÆAƒuƒ‰ƒXƒgƒ}ƒCƒ“AƒNƒŒƒCƒ‚ƒA[ƒgƒ‰ƒbƒv‚Ì‚Ý + if (!(skill_get_unit_flag(group->skill_id)&UF_DANCE) && + group->skill_id!=HT_CLAYMORETRAP && group->skill_id!=HT_BLASTMINE) return 0; - if(group->unit!=NULL){ - if(!battle_config.unit_movement_type){ - int i; - for(i=0;i<group->unit_count;i++){ - struct skill_unit *unit=&group->unit[i]; - if(unit->alive && !(m==unit->bl.m && dx==0 && dy==0)){ - int range=unit->range; - map_delblock(&unit->bl); - unit->bl.m = m; - unit->bl.x += dx; - unit->bl.y += dy; - map_addblock(&unit->bl); - clif_skill_setunit(unit); - if(range>0){ - if(range<7) - range=7; - map_foreachinarea( skill_unit_move_unit_group_sub, unit->bl.m, - unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0, - &unit->bl,gettick() ); - } - } + m_flag = (int *) aMalloc(sizeof(int)*group->unit_count); + memset(m_flag,0,sizeof(int)*group->unit_count);// ˆÚ“®ƒtƒ‰ƒO + // æ‚Ƀtƒ‰ƒO‚ð‘S•”Œˆ‚ß‚é + // m_flag + // 0: ’PƒˆÚ“® + // 1: ƒ†ƒjƒbƒg‚ðˆÚ“®‚·‚é(Œ»ˆÊ’u‚©‚烆ƒjƒbƒg‚ª‚È‚‚È‚é) + // 2: Žc—¯•VˆÊ’u‚ªˆÚ“®æ‚ƂȂé(ˆÚ“®æ‚Ƀ†ƒjƒbƒg‚ª‘¶Ý‚µ‚È‚¢) + // 3: Žc—¯ + for(i=0;i<group->unit_count;i++){ + unit1=&group->unit[i]; + if (!unit1->alive || unit1->bl.m!=m) + continue; + for(j=0;j<group->unit_count;j++){ + unit2=&group->unit[j]; + if (!unit2->alive) + continue; + if (unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){ + // ˆÚ“®æ‚Ƀ†ƒjƒbƒg‚ª‚©‚Ô‚Á‚Ä‚¢‚é + m_flag[i] |= 0x1; } - }else{ - int i,j, *r_flag, *s_flag, *m_flag; - struct skill_unit *unit1; - struct skill_unit *unit2; - r_flag = (int *) malloc(sizeof(int) * group->unit_count); - s_flag = (int *) malloc(sizeof(int) * group->unit_count); - m_flag = (int *) malloc(sizeof(int) * group->unit_count); - memset(r_flag,0, sizeof(int) * group->unit_count);// ?³ƒtƒ‰ƒO - memset(s_flag,0, sizeof(int) * group->unit_count);// ?³ƒtƒ‰ƒO - memset(m_flag,0, sizeof(int) * group->unit_count);// ?³ƒtƒ‰ƒO - - //æ‚Ƀtƒ‰ƒO‚ð‘S•”Œˆ‚ß‚é - for(i=0;i<group->unit_count;i++){ - int move_check=0;// ‚©‚Ô‚èƒtƒ‰ƒO - unit1=&group->unit[i]; - for(j=0;j<group->unit_count;j++){ - unit2=&group->unit[j]; - if(unit1->bl.m==m && unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){ - //ˆÚ“®æ‚Ƀ†ƒjƒbƒg‚ª‚©‚Ô‚Á‚Ä‚½‚ç - s_flag[i]=1;// ˆÚ“®‘O‚̃†ƒjƒbƒgƒiƒ“ƒo?‚Ì?³ƒtƒ‰ƒOon - r_flag[j]=1;// ‚©‚Ԃ郆ƒjƒbƒgƒiƒ“ƒo?‚Ì?—¯ƒtƒ‰ƒOon - move_check=1;//ƒ†ƒjƒbƒg‚ª‚©‚Ô‚Á‚½B - break; - } - } - if(!move_check)// ƒ†ƒjƒbƒg‚ª‚©‚Ô‚Á‚ĂȂ©‚Á‚½‚ç - m_flag[i]=1;// ˆÚ“®‘Oƒ†ƒjƒbƒgƒiƒ“ƒo?‚̈ړ®ƒtƒ‰ƒOon - } - - //ƒtƒ‰ƒO‚ÉŠî‚¢‚ă†ƒjƒbƒgˆÚ“® - for(i=0;i<group->unit_count;i++){ - unit1=&group->unit[i]; - if(m_flag[i]){// ˆÚ“®ƒtƒ‰ƒO‚ªon‚Å - if(!r_flag[i]){// ?—¯ƒtƒ‰ƒO‚ªoff‚È‚ç - //?ƒˆÚ“®(range‚à?³‚Ì•K—v–³‚µ) - int range=unit1->range; - map_delblock(&unit1->bl); - unit1->bl.m = m; - unit1->bl.x += dx; - unit1->bl.y += dy; - map_addblock(&unit1->bl); - clif_skill_setunit(unit1); - if(range > 0){ - if(range < 7) - range = 7; - map_foreachinarea( skill_unit_move_unit_group_sub, unit1->bl.m, - unit1->bl.x-range,unit1->bl.y-range,unit1->bl.x+range,unit1->bl.y+range,0, - &unit1->bl,gettick() ); - } - }else{// ?—¯ƒtƒ‰ƒO‚ªon‚È‚ç - //‹óƒ†ƒjƒbƒg‚ɂȂé‚Ì‚ÅA?³‰Â”\‚ȃ†ƒjƒbƒg‚ð’T‚· - for(j=0;j<group->unit_count;j++){ - unit2=&group->unit[j]; - if(s_flag[j] && !r_flag[j]){ - // ?³ˆÚ“®(range?³•t‚«) - int range=unit1->range; - map_delblock(&unit2->bl); - unit2->bl.m = m; - unit2->bl.x = unit1->bl.x + dx; - unit2->bl.y = unit1->bl.y + dy; - unit2->range = unit1->range; - map_addblock(&unit2->bl); - clif_skill_setunit(unit2); - if(range > 0){ - if(range < 7) - range = 7; - map_foreachinarea( skill_unit_move_unit_group_sub, unit2->bl.m, - unit2->bl.x-range,unit2->bl.y-range,unit2->bl.x+range,unit2->bl.y+range,0, - &unit2->bl,gettick() ); - } - s_flag[j]=0;// ?³Š®—¹‚µ‚½‚Ì‚Åoff - break; - } - } - } + if (unit1->bl.x-dx==unit2->bl.x && unit1->bl.y-dy==unit2->bl.y){ + // ƒ†ƒjƒbƒg‚ª‚±‚Ìꊂɂâ‚Á‚Ä‚‚é + m_flag[i] |= 0x2; + } + } + } + // ƒtƒ‰ƒO‚ÉŠî‚¢‚ă†ƒjƒbƒgˆÚ“® + // ƒtƒ‰ƒO‚ª1‚Ìunit‚ð’T‚µAƒtƒ‰ƒO‚ª2‚Ìunit‚̈ړ®æ‚Ɉڂ· + j = 0; + for (i=0;i<group->unit_count;i++) { + unit1=&group->unit[i]; + if (!unit1->alive) + continue; + if (!(m_flag[i]&0x2)) { + // ƒ†ƒjƒbƒg‚ª‚È‚‚È‚éꊂŃXƒLƒ‹ƒ†ƒjƒbƒg‰e‹¿‚ðÁ‚· + map_foreachinarea(skill_unit_effect,unit1->bl.m, + unit1->bl.x,unit1->bl.y,unit1->bl.x,unit1->bl.y,0, + &unit1->bl,tick,0); + } + if (m_flag[i]==0) { + // ’PƒˆÚ“® + map_delblock(&unit1->bl); + unit1->bl.m = m; + unit1->bl.x += dx; + unit1->bl.y += dy; + map_addblock(&unit1->bl); + clif_skill_setunit(unit1); + } else if (m_flag[i]==1) { + // ƒtƒ‰ƒO‚ª2‚Ì‚à‚Ì‚ð’T‚µ‚Ä‚»‚̃†ƒjƒbƒg‚̈ړ®æ‚Ɉړ® + for(;j<group->unit_count;j++) { + if (m_flag[j]==2) { + // Œp³ˆÚ“® + unit2 = &group->unit[j]; + if (!unit2->alive) + continue; + map_delblock(&unit1->bl); + unit1->bl.m = m; + unit1->bl.x = unit2->bl.x+dx; + unit1->bl.y = unit2->bl.y+dy; + map_addblock(&unit1->bl); + clif_skill_setunit(unit1); + j++; + break; } } - free(r_flag); - free(s_flag); - free(m_flag); + } + if (!(m_flag[i]&0x2)) { + // ˆÚ“®Œã‚ÌꊂŃXƒLƒ‹ƒ†ƒjƒbƒg‚𔓮 + map_foreachinarea(skill_unit_effect,unit1->bl.m, + unit1->bl.x,unit1->bl.y,unit1->bl.x,unit1->bl.y,0, + &unit1->bl,tick,1); } } + aFree(m_flag); return 0; } @@ -10935,62 +8847,57 @@ int skill_produce_mix( struct map_session_data *sd, /* Šm—¦”»’è */ equip = itemdb_isequip(nameid); if(!equip) { +// Corrected rates [DracoRPG] --------------------------// if(skill_produce_db[idx].req_skill==AM_PHARMACY) { - if((nameid >= 501 && nameid <= 506) || (nameid >= 545 && nameid <= 547) || nameid == 525) - make_per = 2000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_POTIONPITCHER)*100; - else if(nameid == 970) - make_per = 1500 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300; - else if(nameid == 7135) - make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_DEMONSTRATION)*100; - else if(nameid == 7136) - make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_ACIDTERROR)*100; - else if(nameid == 7137) - make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CANNIBALIZE)*100; - else if(nameid == 7138) - make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_SPHEREMINE)*100; - else if(nameid == 7139) - make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CP_WEAPON)*100 + - pc_checkskill(sd,AM_CP_SHIELD)*100 + pc_checkskill(sd,AM_CP_ARMOR)*100 + pc_checkskill(sd,AM_CP_HELM)*100; - else - make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300; + make_per = pc_checkskill(sd,AM_LEARNINGPOTION)*100 + + pc_checkskill(sd,AM_PHARMACY)*300 + sd->status.job_level*20 + + sd->paramc[4]*10+sd->paramc[5]*10; + + if(nameid >= 501 && nameid <= 505) // Normal potions + make_per += 2000 + pc_checkskill(sd,AM_POTIONPITCHER)*100; + else if(nameid >= 605 && nameid <= 606) // Anodyne & Aloevera (not sure of the formula, I put the same base value as normal pots but without the Aid Potion bonus since they are not throwable pots ^^) + make_per += 2000; + else if(nameid >= 545 && nameid <= 547) // Concentrated potions + ; + else if(nameid == 970) // Alcohol + make_per += 1000; + else if(nameid == 7135) // Bottle Grenade + make_per += 500 + pc_checkskill(sd,AM_DEMONSTRATION)*100; + else if(nameid == 7136) // Acid Bottle + make_per += 500 + pc_checkskill(sd,AM_ACIDTERROR)*100; + else if(nameid == 7137) // Plant Bottle + make_per += 500 + pc_checkskill(sd,AM_CANNIBALIZE)*100; + else if(nameid == 7138) // Marine Sphere Bottle + make_per += 500 + pc_checkskill(sd,AM_SPHEREMINE)*100; + else if(nameid == 7139) // Glistening Coat + make_per += 500 + pc_checkskill(sd,AM_CP_WEAPON)*100 + pc_checkskill(sd,AM_CP_SHIELD)*100 + + pc_checkskill(sd,AM_CP_ARMOR)*100 + pc_checkskill(sd,AM_CP_HELM)*100; } else if (skill_produce_db[idx].req_skill == ASC_CDP) { make_per = 2000 + 40*sd->paramc[4] + 20*sd->paramc[5]; - //make_per = 20 + (20*sd->paramc[4])/50 + (20*sd->paramc[5])/100; } else { if(nameid == 998) - make_per = 2000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*600; - else if(nameid == 985) - make_per = 1000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + (pc_checkskill(sd,skill_produce_db[idx].req_skill)-1)*500; + make_per = 1500 + sd->status.job_level*35 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*600; else - make_per = 1000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500; - } - } - else { - int add_per; - if(pc_search_inventory(sd,989) >= 0) add_per = 750; - else if(pc_search_inventory(sd,988) >= 0) add_per = 500; - else if(pc_search_inventory(sd,987) >= 0) add_per = 250; - else if(pc_search_inventory(sd,986) >= 0) add_per = 0; - else add_per = -500; - if(ele) add_per -= 500; - add_per -= sc*500; + make_per = 1000 + sd->status.job_level*35 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500; + } + if(battle_config.pp_rate != 100) + make_per = make_per * battle_config.pp_rate / 100; + } else { // Corrected rates [DracoRPG] + int add_per=0; + if(pc_search_inventory(sd,989) >= 0) add_per = 400; + else if(pc_search_inventory(sd,988) >= 0) add_per = 300; + else if(pc_search_inventory(sd,987) >= 0) add_per = 200; + else if(pc_search_inventory(sd,986) >= 0) add_per = 100; wlv = itemdb_wlv(nameid); - make_per = ((250 + sd->status.base_level*15 + sd->paramc[4]*10 + sd->paramc[5]*5 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500 + - add_per) * (100 - (wlv - 1)*20))/100 + pc_checkskill(sd,BS_WEAPONRESEARCH)*100 + ((wlv >= 3)? pc_checkskill(sd,BS_ORIDEOCON)*100 : 0); + make_per = 1500 + sd->status.job_level*35 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*1000 + pc_checkskill(sd,BS_WEAPONRESEARCH)*100 + + ((wlv >= 3)? pc_checkskill(sd,BS_ORIDEOCON)*100 : 0) + add_per - (ele? 2500:0) - sc*((4-wlv)*500) - wlv*1000; + if(battle_config.wp_rate != 100) /* Šm—¦•â³ */ + make_per = make_per * battle_config.wp_rate / 100; } +// -----------------------------------------------------// if(make_per < 1) make_per = 1; - if(skill_produce_db[idx].req_skill==AM_PHARMACY || - skill_produce_db[idx].req_skill==ASC_CDP) { - if( battle_config.pp_rate!=100 ) - make_per=make_per*battle_config.pp_rate/100; - } - else { - if( battle_config.wp_rate!=100 ) /* Šm—¦•â³ */ - make_per=make_per*battle_config.wp_rate/100; - } - // if(battle_config.etc_log) // printf("make rate = %d\n",make_per); @@ -11013,10 +8920,8 @@ int skill_produce_mix( struct map_session_data *sd, *((unsigned long *)(&tmp_item.card[2]))=sd->char_id; /* ƒLƒƒƒ‰ID */ } - #ifndef TXT_ONLY if(log_config.produce > 0) log_produce(sd,nameid,slot1,slot2,slot3,1); - #endif //USE_SQL switch (skill_produce_db[idx].req_skill) { case AM_PHARMACY: @@ -11037,12 +8942,9 @@ int skill_produce_mix( struct map_session_data *sd, clif_additem(sd,0,0,flag); map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); } - } - else { - #ifndef TXT_ONLY + } else { if(log_config.produce > 0) log_produce(sd,nameid,slot1,slot2,slot3,0); - #endif //USE_SQL switch (skill_produce_db[idx].req_skill) { case AM_PHARMACY: @@ -11110,6 +9012,230 @@ int skill_arrow_create( struct map_session_data *sd,int nameid) * ‰Šú‰»Œn */ +/*---------------------------------------------------------------------------- + * ‰Šú‰»Œn + */ + +/* + * •¶Žš—ñˆ— + * ',' ‚Å‹æØ‚Á‚Ä val ‚É–ß‚· + */ +int skill_split_str(char *str,char **val,int num) +{ + int i; + + for (i=0; i<num && str; i++){ + val[i] = str; + str = strchr(str,','); + if (str) + *str++=0; + } + return i; +} +/* + * •¶Žš—ñˆ— + * ':' ‚Å‹æØ‚Á‚Äatoi‚µ‚Äval‚É–ß‚· + */ +int skill_split_atoi(char *str,int *val) +{ + int i, max = 0; + + for (i=0; i<MAX_SKILL_LEVEL; i++) { + if (str) { + val[i] = max = atoi(str); + str = strchr(str,':'); + if (str) + *str++=0; + } else { + val[i] = max; + } + } + return i; +} + +/* + * ƒXƒLƒ‹ƒ†ƒjƒbƒg‚Ì”z’uî•ñì¬ + */ +void skill_init_unit_layout() +{ + int i,j,size,pos = 0; + + memset(skill_unit_layout,0,sizeof(skill_unit_layout)); + // ‹éŒ`‚̃†ƒjƒbƒg”z’u‚ð쬂·‚é + for (i=0; i<=MAX_SQUARE_LAYOUT; i++) { + size = i*2+1; + skill_unit_layout[i].count = size*size; + for (j=0; j<size*size; j++) { + skill_unit_layout[i].dx[j] = (j%size-i); + skill_unit_layout[i].dy[j] = (j/size-i); + } + } + pos = i; + // ‹éŒ`ˆÈŠO‚̃†ƒjƒbƒg”z’u‚ð쬂·‚é + for (i=0;i<MAX_SKILL_DB;i++) { + if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1) + continue; + switch (i) { + case MG_FIREWALL: + case WZ_ICEWALL: + // ƒtƒ@ƒCƒA[ƒEƒH[ƒ‹AƒAƒCƒXƒEƒH[ƒ‹‚Í•ûŒü‚ŕςí‚é‚̂ŕʈ— + break; + case PR_SANCTUARY: + { + static const int dx[] = { + -1, 0, 1,-2,-1, 0, 1, 2,-2,-1, + 0, 1, 2,-2,-1, 0, 1, 2,-1, 0, 1}; + static const int dy[]={ + -2,-2,-2,-1,-1,-1,-1,-1, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2}; + skill_unit_layout[pos].count = 21; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case PR_MAGNUS: + { + static const int dx[] = { + -1, 0, 1,-1, 0, 1,-3,-2,-1, 0, + 1, 2, 3,-3,-2,-1, 0, 1, 2, 3, + -3,-2,-1, 0, 1, 2, 3,-1, 0, 1,-1, 0, 1}; + static const int dy[] = { + -3,-3,-3,-2,-2,-2,-1,-1,-1,-1, + -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3}; + skill_unit_layout[pos].count = 33; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case AS_VENOMDUST: + { + static const int dx[] = {-1, 0, 0, 0, 1}; + static const int dy[] = { 0,-1, 0, 1, 0}; + skill_unit_layout[pos].count = 5; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case CR_GRANDCROSS: + case NPC_DARKGRANDCROSS: + { + static const int dx[] = { + 0, 0,-1, 0, 1,-2,-1, 0, 1, 2, + -4,-3,-2,-1, 0, 1, 2, 3, 4,-2, + -1, 0, 1, 2,-1, 0, 1, 0, 0}; + static const int dy[] = { + -4,-3,-2,-2,-2,-1,-1,-1,-1,-1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 2, 2, 2, 3, 4}; + skill_unit_layout[pos].count = 29; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case PF_FOGWALL: + { + static const int dx[] = { + -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2}; + static const int dy[] = { + -1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}; + skill_unit_layout[pos].count = 15; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case PA_GOSPEL: + { + static const int dx[] = { + -1, 0, 1,-1, 0, 1,-3,-2,-1, 0, + 1, 2, 3,-3,-2,-1, 0, 1, 2, 3, + -3,-2,-1, 0, 1, 2, 3,-1, 0, 1, + -1, 0, 1}; + static const int dy[] = { + -3,-3,-3,-2,-2,-2,-1,-1,-1,-1, + -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 3, 3, 3}; + skill_unit_layout[pos].count = 33; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + default: + printf("unknown unit layout at skill %d\n",i); + break; + } + if (!skill_unit_layout[pos].count) + continue; + for (j=0;j<MAX_SKILL_LEVEL;j++) + skill_db[i].unit_layout_type[j] = pos; + pos++; + } + // ƒtƒ@ƒCƒ„[ƒEƒH[ƒ‹ + firewall_unit_pos = pos; + for (i=0;i<8;i++) { + if (i&1) { /* ŽÎ‚ß”z’u */ + skill_unit_layout[pos].count = 5; + if (i&0x2) { + int dx[] = {-1,-1, 0, 0, 1}; + int dy[] = { 1, 0, 0,-1,-1}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } else { + int dx[] = { 1, 1 ,0, 0,-1}; + int dy[] = { 1, 0, 0,-1,-1}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } else { /* c‰¡”z’u */ + skill_unit_layout[pos].count = 3; + if (i%4==0) { /* ㉺ */ + int dx[] = {-1, 0, 1}; + int dy[] = { 0, 0, 0}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } else { /* ¶‰E */ + int dx[] = { 0, 0, 0}; + int dy[] = {-1, 0, 1}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } + pos++; + } + // ƒAƒCƒXƒEƒH[ƒ‹ + icewall_unit_pos = pos; + for (i=0;i<8;i++) { + skill_unit_layout[pos].count = 5; + if (i&1) { /* ŽÎ‚ß”z’u */ + if (i&0x2) { + int dx[] = {-2,-1, 0, 1, 2}; + int dy[] = { 2,-1, 0,-1,-2}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } else { + int dx[] = { 2, 1 ,0,-1,-2}; + int dy[] = { 2, 1, 0,-1,-2}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } else { /* c‰¡”z’u */ + if (i%4==0) { /* ㉺ */ + int dx[] = {-2,-1, 0, 1, 2}; + int dy[] = { 0, 0, 0, 0, 0}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } else { /* ¶‰E */ + int dx[] = { 0, 0, 0, 0, 0}; + int dy[] = {-2,-1, 0, 1, 2}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } + pos++; + } +} + /*========================================== * ƒXƒLƒ‹?ŒWƒtƒ@ƒCƒ‹?‚Ý?‚Ý * skill_db.txt ƒXƒLƒ‹ƒf?ƒ^ @@ -11134,46 +9260,27 @@ int skill_readdb(void) return 1; } while(fgets(line,1020,fp)){ - char *split[50], *split2[MAX_SKILL_LEVEL]; + char *split[50]; if(line[0]=='/' && line[1]=='/') continue; - for(j=0,p=line;j<14 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,14); if(split[13]==NULL || j<14) continue; i=atoi(split[0]); if (i>=10000 && i<10015) // for guild skills [Celest] i -= 9500; - else if(i<0 || i>MAX_SKILL_DB) + else if(i<=0 || i>MAX_SKILL_DB) continue; /* printf("skill id=%d\n",i); */ - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].range[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[1],skill_db[i].range); skill_db[i].hit=atoi(split[2]); skill_db[i].inf=atoi(split[3]); skill_db[i].pl=atoi(split[4]); skill_db[i].nk=atoi(split[5]); skill_db[i].max=atoi(split[6]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[7];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].num[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[7],skill_db[i].num); if(strcmpi(split[8],"yes") == 0) skill_db[i].castcancel=1; @@ -11190,17 +9297,11 @@ int skill_readdb(void) skill_db[i].skill_type=BF_MISC; else skill_db[i].skill_type=0; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[13];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].blewcount[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[13],skill_db[i].blewcount); } fclose(fp); - printf("read db/skill_db.txt done\n"); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_db.txt"); + ShowStatus(tmp_output); fp=fopen("db/skill_require_db.txt","r"); if(fp==NULL){ @@ -11208,91 +9309,39 @@ int skill_readdb(void) return 1; } while(fgets(line,1020,fp)){ - char *split[51], *split2[MAX_SKILL_LEVEL]; + char *split[50]; if(line[0]=='/' && line[1]=='/') continue; - for(j=0,p=line;j<30 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,30); if(split[29]==NULL || j<30) continue; i=atoi(split[0]); if (i>=10000 && i<10015) // for guild skills [Celest] i -= 9500; - else if(i<0 || i>MAX_SKILL_DB) + else if(i<=0 || i>MAX_SKILL_DB) continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].hp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].mhp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].sp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].hp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[5];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].sp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[6];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].zeny[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[7];j<32 && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<32 && split2[k];k++) { - l = atoi(split2[k]); - if(l == 99) { + skill_split_atoi(split[1],skill_db[i].hp); + skill_split_atoi(split[2],skill_db[i].mhp); + skill_split_atoi(split[3],skill_db[i].sp); + skill_split_atoi(split[4],skill_db[i].hp_rate); + skill_split_atoi(split[5],skill_db[i].sp_rate); + skill_split_atoi(split[6],skill_db[i].zeny); + + p = split[7]; + for(j=0;j<32;j++){ + l = atoi(p); + if (l==99) { skill_db[i].weapon = 0xffffffff; break; } else skill_db[i].weapon |= 1<<l; + p=strchr(p,':'); + if(!p) + break; + p++; } if( strcmpi(split[8],"hiding")==0 ) skill_db[i].state=ST_HIDING; @@ -11309,14 +9358,7 @@ int skill_readdb(void) else if( strcmpi(split[8],"water")==0 ) skill_db[i].state=ST_WATER; else skill_db[i].state=ST_NONE; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[9];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].spiritball[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[9],skill_db[i].spiritball); skill_db[i].itemid[0]=atoi(split[10]); skill_db[i].amount[0]=atoi(split[11]); skill_db[i].itemid[1]=atoi(split[12]); @@ -11339,7 +9381,8 @@ int skill_readdb(void) skill_db[i].amount[9]=atoi(split[29]); } fclose(fp); - printf("read db/skill_require_db.txt done\n"); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_require_db.txt"); + ShowStatus(tmp_output); /* ƒLƒƒƒXƒeƒBƒ“ƒOƒf?ƒ^ƒx?ƒX */ fp=fopen("db/skill_cast_db.txt","r"); @@ -11348,62 +9391,70 @@ int skill_readdb(void) return 1; } while(fgets(line,1020,fp)){ - char *split[50], *split2[MAX_SKILL_LEVEL]; + char *split[50]; memset(split,0,sizeof(split)); // [Valaris] thanks to fov if(line[0]=='/' && line[1]=='/') continue; - for(j=0,p=line;j<5 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,5); if(split[4]==NULL || j<5) continue; i=atoi(split[0]); if (i>=10000 && i<10015) // for guild skills [Celest] i -= 9500; - else if(i<0 || i>MAX_SKILL_DB) + else if(i<=0 || i>MAX_SKILL_DB) continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].cast[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].delay[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[1],skill_db[i].cast); + skill_split_atoi(split[2],skill_db[i].delay); + skill_split_atoi(split[3],skill_db[i].upkeep_time); + skill_split_atoi(split[4],skill_db[i].upkeep_time2); + } + fclose(fp); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_cast_db.txt"); + ShowStatus(tmp_output); - memset(split2,0,sizeof(split2)); - for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].upkeep_time[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + /* ƒXƒLƒ‹ƒ†ƒjƒbƒgƒf[ƒ^ƒx[ƒX */ + fp = fopen("db/skill_unit_db.txt","r"); + if (fp==NULL) { + printf("can't read db/skill_unit_db.txt\n"); + return 1; + } + k = 0; + while (fgets(line,1020,fp)) { + char *split[50]; + if (line[0]=='/' && line[1]=='/') + continue; + j = skill_split_str(line,split,8); + if (split[7]==NULL || j<8) + continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].upkeep_time2[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + i=atoi(split[0]); + if (i>=10000 && i<10015) // for guild skills [Celest] + i -= 9500; + else if(i<=0 || i>MAX_SKILL_DB) + continue; + skill_db[i].unit_id[0] = strtol(split[1],NULL,16); + skill_db[i].unit_id[1] = strtol(split[2],NULL,16); + skill_split_atoi(split[3],skill_db[i].unit_layout_type); + skill_db[i].unit_range = atoi(split[4]); + skill_db[i].unit_interval = atoi(split[5]); + + if( strcmpi(split[6],"noenemy")==0 ) skill_db[i].unit_target=BCT_NOENEMY; + else if( strcmpi(split[6],"friend")==0 ) skill_db[i].unit_target=BCT_NOENEMY; + else if( strcmpi(split[6],"party")==0 ) skill_db[i].unit_target=BCT_PARTY; + else if( strcmpi(split[6],"all")==0 ) skill_db[i].unit_target=BCT_ALL; + else if( strcmpi(split[6],"enemy")==0 ) skill_db[i].unit_target=BCT_ENEMY; + else if( strcmpi(split[6],"self")==0 ) skill_db[i].unit_target=BCT_SELF; + else skill_db[i].unit_target = strtol(split[6],NULL,16); + + skill_db[i].unit_flag = strtol(split[7],NULL,16); + k++; } fclose(fp); - printf("read db/skill_cast_db.txt done\n"); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_unit_db.txt"); + ShowStatus(tmp_output); + skill_init_unit_layout(); /* »‘¢ŒnƒXƒLƒ‹ƒf?ƒ^ƒx?ƒX */ memset(skill_produce_db,0,sizeof(skill_produce_db)); @@ -11422,16 +9473,11 @@ int skill_readdb(void) if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<3 + MAX_PRODUCE_RESOURCE * 2 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - if(split[0]==NULL) + j = skill_split_str(line,split,(3 + MAX_PRODUCE_RESOURCE * 2)); + if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); - if(i<=0) - continue; + if(i<=0) continue; skill_produce_db[k].nameid=i; skill_produce_db[k].itemlv=atoi(split[1]); @@ -11446,7 +9492,8 @@ int skill_readdb(void) break; } fclose(fp); - printf("read %s done (count=%d)\n",filename[m],k); + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",k,filename[m]); + ShowStatus(tmp_output); } memset(skill_arrow_db,0,sizeof(skill_arrow_db)); @@ -11462,12 +9509,8 @@ int skill_readdb(void) if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<13 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - if(split[0]==NULL) + j = skill_split_str(line,split,13); + if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); if(i<=0) @@ -11484,7 +9527,8 @@ int skill_readdb(void) break; } fclose(fp); - printf("read db/create_arrow_db.txt done (count=%d)\n",k); + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",k,"db/create_arrow_db.txt"); + ShowStatus(tmp_output); memset(skill_abra_db,0,sizeof(skill_abra_db)); fp=fopen("db/abra_db.txt","r"); @@ -11498,12 +9542,8 @@ int skill_readdb(void) if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<13 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - if(split[0]==NULL) + j = skill_split_str(line,split,13); + if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); if(i<=0) @@ -11517,7 +9557,8 @@ int skill_readdb(void) break; } fclose(fp); - printf("read db/abra_db.txt done (count=%d)\n",k); + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",k,"db/abra_db.txt"); + ShowStatus(tmp_output); fp=fopen("db/skill_castnodex_db.txt","r"); if(fp==NULL){ @@ -11525,33 +9566,27 @@ int skill_readdb(void) return 1; } while(fgets(line,1020,fp)){ - char *split[50], *split2[MAX_SKILL_LEVEL]; - memset(split,0,sizeof(split)); + char *split[50]; if(line[0]=='/' && line[1]=='/') continue; - for(j=0,p=line;j<2 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - + memset(split,0,sizeof(split)); + j = skill_split_str(line,split,3); + if(split[0]==0) //fixed by Lupus + continue; i=atoi(split[0]); if (i>=10000 && i<10015) // for guild skills [Celest] i -= 9500; - else if(i<0 || i>MAX_SKILL_DB) + else if(i<=0 || i>MAX_SKILL_DB) continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].castnodex[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[1],skill_db[i].castnodex); + if (!split[2]) + continue; + skill_split_atoi(split[2],skill_db[i].delaynodex); } fclose(fp); - printf("read db/skill_castnodex_db.txt done\n"); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_castnodex_db.txt"); + ShowStatus(tmp_output); fp=fopen("db/skill_nocast_db.txt","r"); if(fp==NULL){ @@ -11564,35 +9599,75 @@ int skill_readdb(void) if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<2 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - if(split[0]==NULL) + j = skill_split_str(line,split,2); + if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); - if(i < 0 || i > MAX_SKILL_DB) + if (i>=10000 && i<10015) // for guild skills [Celest] + i -= 9500; + else if(i<=0 || i>MAX_SKILL_DB) continue; skill_db[i].nocast=atoi(split[1]); k++; } fclose(fp); - printf("read db/skill_nocast_db done\n"); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_nocast_db"); + ShowStatus(tmp_output); return 0; } -void skill_reload(void) +/*=============================================== + * For reading leveluseskillspamount.txt [Celest] + *----------------------------------------------- + */ +static int skill_read_skillspamount(void) { - /* + char *buf,*p; + struct skill_db *skill = NULL; + int s, idx, new_flag=1, level=1, sp=0; + + buf=(char *) grfio_reads("data\\leveluseskillspamount.txt",&s); + + if(buf==NULL) + return -1; + + buf[s]=0; + for(p=buf;p-buf<s;){ + char buf2[64]; + + if (sscanf(p,"%[@]",buf2) == 1) { + level = 1; + new_flag = 1; + } else if (new_flag && sscanf(p,"%[^#]#",buf2) == 1) { + for (idx=0; skill_names[idx].id != 0; idx++) { + if (strstr(buf2, skill_names[idx].name) != NULL) { + skill = &skill_db[ skill_names[idx].id ]; + new_flag = 0; + break; + } + } + } else if (!new_flag && sscanf(p,"%d#",&sp) == 1) { + skill->sp[level-1]=sp; + level++; + } - <empty skill database> - <?> + p=strchr(p,10); + if(!p) break; + p++; + } + aFree(buf); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\leveluseskillspamount.txt"); + ShowStatus(tmp_output); - */ + return 0; +} - do_init_skill(); +void skill_reload(void) +{ + skill_readdb(); + if (battle_config.skill_sp_override_grffile) + skill_read_skillspamount(); } /*========================================== @@ -11602,12 +9677,13 @@ void skill_reload(void) int do_init_skill(void) { skill_readdb(); + if (battle_config.skill_sp_override_grffile) + skill_read_skillspamount(); add_timer_func_list(skill_unit_timer,"skill_unit_timer"); add_timer_func_list(skill_castend_id,"skill_castend_id"); add_timer_func_list(skill_castend_pos,"skill_castend_pos"); add_timer_func_list(skill_timerskill,"skill_timerskill"); - add_timer_func_list(skill_status_change_timer,"skill_status_change_timer"); add_timer_interval(gettick()+SKILLUNITTIMER_INVERVAL,skill_unit_timer,0,0,SKILLUNITTIMER_INVERVAL); return 0; diff --git a/src/map/skill.h b/src/map/skill.h index a8bf30e3c..67d7a906c 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -1,10 +1,10 @@ -// $Id: skill.h,v 1.5 2004/11/26 5:47:12 PM Celestia Exp $ +// $Id: skill.h,v 1.5 2004/12/23 7:43:16 PM Celestia $ #ifndef _SKILL_H_ #define _SKILL_H_ #include "map.h" -#define MAX_SKILL_DB 515 +#define MAX_SKILL_DB 750 #define MAX_SKILL_PRODUCE_DB 150 #define MAX_PRODUCE_RESOURCE 7 #define MAX_SKILL_ARROW_DB 150 @@ -23,7 +23,14 @@ struct skill_db { int weapon,state,spiritball[MAX_SKILL_LEVEL]; int itemid[10],amount[10]; int castnodex[MAX_SKILL_LEVEL]; + int delaynodex[MAX_SKILL_LEVEL]; int nocast; + int unit_id[2]; + int unit_layout_type[MAX_SKILL_LEVEL]; + int unit_range; + int unit_interval; + int unit_target; + int unit_flag; }; extern struct skill_db skill_db[MAX_SKILL_DB]; @@ -34,6 +41,24 @@ struct skill_name_db { }; extern const struct skill_name_db skill_names[]; +#define MAX_SKILL_UNIT_LAYOUT 50 +#define MAX_SQUARE_LAYOUT 5 // 11*11‚̃†ƒjƒbƒg”z’u‚ªÅ‘å +#define MAX_SKILL_UNIT_COUNT ((MAX_SQUARE_LAYOUT*2+1)*(MAX_SQUARE_LAYOUT*2+1)) +struct skill_unit_layout { + int count; + int dx[MAX_SKILL_UNIT_COUNT]; + int dy[MAX_SKILL_UNIT_COUNT]; +}; + +enum { + UF_DEFNOTENEMY = 0x0001, // defnotenemy Ý’è‚ÅBCT_NOENEMY‚ÉØ‚è‘Ö‚¦ + UF_NOREITERATION = 0x0002, // d•¡’u‚«‹ÖŽ~ + UF_NOFOOTSET = 0x0004, // ‘«Œ³’u‚«‹ÖŽ~ + UF_NOOVERLAP = 0x0008, // ƒ†ƒjƒbƒgŒø‰Ê‚ªd•¡‚µ‚È‚¢ + UF_DANCE = 0x0100, // ƒ_ƒ“ƒXƒXƒLƒ‹ + UF_ENSEMBLE = 0x0200, // ‡‘tƒXƒLƒ‹ +}; + // ƒAƒCƒeƒ€ì¬ƒf?ƒ^ƒx?ƒX struct skill_produce_db { int nameid, trigger; @@ -57,6 +82,9 @@ struct skill_abra_db { }; extern struct skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB]; +extern int enchant_eff[5]; +extern int deluge_eff[5]; + struct block_list; struct map_session_data; struct skill_unit; @@ -86,6 +114,7 @@ int skill_get_unit_id(int id,int flag); int skill_get_inf2( int id ); int skill_get_maxcount( int id ); int skill_get_blewcount( int id ,int lv ); +int skill_get_unit_flag( int id ); int skill_tree_get_max( int id, int b_class ); // Celest // ƒXƒLƒ‹‚ÌŽg—p @@ -109,9 +138,6 @@ int skill_delunit(struct skill_unit *unit); struct skill_unit_group *skill_initunitgroup(struct block_list *src, int count,int skillid,int skilllv,int unit_id); int skill_delunitgroup(struct skill_unit_group *group); -struct skill_unit_group_tickset *skill_unitgrouptickset_search( - struct block_list *bl,int group_id); -int skill_unitgrouptickset_delete(struct block_list *bl,int group_id); int skill_clear_unitgroup(struct block_list *src); int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl, @@ -119,21 +145,25 @@ int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl, int skill_castfix( struct block_list *bl, int time ); int skill_delayfix( struct block_list *bl, int time ); -int skill_check_unit_range(int m,int x,int y,int range,int skillid); -int skill_check_unit_range2(int m,int x,int y,int range); +int skill_check_unit_range(int m,int x,int y,int skillid, int skilllv); +int skill_check_unit_range2(struct block_list *bl,int m,int x,int y,int skillid, int skilllv); // -- moonsoul (added skill_check_unit_cell) int skill_check_unit_cell(int skillid,int m,int x,int y,int unit_id); int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range); -int skill_unit_move( struct block_list *bl,unsigned int tick,int range); +int skill_unit_move(struct block_list *bl,unsigned int tick,int flag); int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy); struct skill_unit_group *skill_check_dancing( struct block_list *src ); void skill_stop_dancing(struct block_list *src, int flag); +// Guild skills [celest] +int skill_guildaura_sub (struct block_list *bl,va_list ap); + // ‰r¥ƒLƒƒƒ“ƒZƒ‹ int skill_castcancel(struct block_list *bl,int type); int skill_gangsterparadise(struct map_session_data *sd ,int type); +int skill_check_moonlit (struct block_list *bl, int dx, int dy); void skill_brandishspear_first(struct square *tc,int dir,int x,int y); void skill_brandishspear_dir(struct square *tc,int dir,int are); int skill_autospell(struct map_session_data *md,int skillid); @@ -142,19 +172,13 @@ void skill_devotion2(struct block_list *bl,int crusader); int skill_devotion3(struct block_list *bl,int target); void skill_devotion_end(struct map_session_data *md,struct map_session_data *sd,int target); -#define skill_calc_heal(bl,skill_lv) (( battle_get_lv(bl)+battle_get_int(bl) )/8 *(4+ skill_lv*8)) +#define skill_calc_heal(bl,skill_lv) (( status_get_lv(bl)+status_get_int(bl) )/8 *(4+ skill_lv*8)) // ‚»‚Ì‘¼ int skill_check_cloaking(struct block_list *bl); -int skill_type_cloaking(struct block_list *bl); -int skill_is_danceskill(int id); // ƒXƒe?ƒ^ƒXˆÙí -int skill_status_change_start(struct block_list *bl,int type,int val1,int val2,int val3,int val4,int tick,int flag); -int skill_status_change_timer(int tid, unsigned int tick, int id, int data); -int skill_encchant_eremental_end(struct block_list *bl, int type); -int skill_status_change_end( struct block_list* bl , int type,int tid ); -int skill_status_change_clear(struct block_list *bl,int type); +int skill_enchant_elemental_end(struct block_list *bl, int type); int skillnotok(int skillid, struct map_session_data *sd); // ƒAƒCƒeƒ€ì¬ @@ -180,201 +204,6 @@ enum { ST_RECOV_WEIGHT_RATE,ST_MOVE_ENABLE,ST_WATER, }; -enum { // struct map_session_data ‚Ì status_change‚Ì”Ô?ƒe?ƒuƒ‹ -// SC_SENDMAX–¢?‚̓Nƒ‰ƒCƒAƒ“ƒg‚Ö‚Ì’Ê’m‚ ‚èB -// 2-2ŽŸE‚Ì’l‚͂Ȃñ‚©‚ß‚¿‚á‚‚¿‚á‚Á‚Û‚¢‚̂Ŏb’èB‚½‚Ô‚ñ?X‚³‚ê‚Ü‚·B - SC_SENDMAX =128, - SC_PROVOKE = 0, - SC_ENDURE = 1, - SC_TWOHANDQUICKEN = 2, - SC_CONCENTRATE = 3, - SC_HIDING = 4, - SC_CLOAKING = 5, - SC_ENCPOISON = 6, - SC_POISONREACT = 7, - SC_QUAGMIRE = 8, - SC_ANGELUS = 9, - SC_BLESSING =10, - SC_SIGNUMCRUCIS =11, - SC_INCREASEAGI =12, - SC_DECREASEAGI =13, - SC_SLOWPOISON =14, - SC_IMPOSITIO =15, - SC_SUFFRAGIUM =16, - SC_ASPERSIO =17, - SC_BENEDICTIO =18, - SC_KYRIE =19, - SC_MAGNIFICAT =20, - SC_GLORIA =21, - SC_AETERNA =22, - SC_ADRENALINE =23, - SC_WEAPONPERFECTION =24, - SC_OVERTHRUST =25, - SC_MAXIMIZEPOWER =26, - SC_RIDING =27, - SC_FALCON =28, - SC_TRICKDEAD =29, - SC_LOUD =30, - SC_ENERGYCOAT =31, - SC_HALLUCINATION =34, - SC_WEIGHT50 =35, - SC_WEIGHT90 =36, - SC_SPEEDPOTION0 =37, - SC_SPEEDPOTION1 =38, - SC_SPEEDPOTION2 =39, - SC_STRIPWEAPON =50, - SC_STRIPSHIELD =51, - SC_STRIPARMOR =52, - SC_STRIPHELM =53, - SC_CP_WEAPON =54, - SC_CP_SHIELD =55, - SC_CP_ARMOR =56, - SC_CP_HELM =57, - SC_AUTOGUARD =58, - SC_REFLECTSHIELD =59, - SC_DEVOTION =60, - SC_PROVIDENCE =61, - SC_DEFENDER =62, - SC_AUTOSPELL =65, - SC_SPEARSQUICKEN =68, - SC_EXPLOSIONSPIRITS =86, - SC_STEELBODY =87, - SC_COMBO =89, - SC_FLAMELAUNCHER =90, - SC_FROSTWEAPON =91, - SC_LIGHTNINGLOADER =92, - SC_SEISMICWEAPON =93, - SC_AURABLADE =103, /* ƒI?ƒ‰ƒuƒŒ?ƒh */ - SC_PARRYING =104, /* ƒpƒŠƒCƒ“ƒO */ - SC_CONCENTRATION =105, /* ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ */ - SC_TENSIONRELAX =106, /* ƒeƒ“ƒVƒ‡ƒ“ƒŠƒ‰ƒbƒNƒX */ - SC_BERSERK =107, /* ƒo?ƒT?ƒN */ - SC_ASSUMPTIO =110, /* ƒAƒVƒƒƒ“ƒvƒeƒBƒI */ - SC_MAGICPOWER =113, /* –‚–@—Í?• */ - SC_TRUESIGHT =115, /* ƒgƒDƒ‹?ƒTƒCƒg */ - SC_WINDWALK =116, /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ - SC_MELTDOWN =117, /* ƒƒ‹ƒgƒ_ƒEƒ“ */ - SC_CARTBOOST =118, /* ƒJ?ƒgƒu?ƒXƒg */ - SC_REJECTSWORD =120, /* ƒŠƒWƒFƒNƒgƒ\?ƒh */ - SC_MARIONETTE =121, /* ƒ}ƒŠƒIƒlƒbƒgƒRƒ“ƒgƒ?ƒ‹ */ - SC_HEADCRUSH =124, /* ƒwƒbƒhƒNƒ‰ƒbƒVƒ… */ - SC_JOINTBEAT =125, /* ƒWƒ‡ƒCƒ“ƒgƒr?ƒg */ - - SC_STONE =128, - SC_FREEZE =129, - SC_STAN =130, - SC_SLEEP =131, - SC_POISON =132, - SC_CURSE =133, - SC_SILENCE =134, - SC_CONFUSION =135, - SC_BLIND =136, - SC_DIVINA = SC_SILENCE, - - SC_SAFETYWALL =140, - SC_PNEUMA =141, - SC_WATERBALL =142, - SC_ANKLE =143, - SC_DANCING =144, - SC_KEEPING =145, - SC_BARRIER =146, - - SC_MAGICROD =149, - SC_SIGHT =150, - SC_RUWACH =151, - SC_AUTOCOUNTER =152, - SC_VOLCANO =153, - SC_DELUGE =154, - SC_VIOLENTGALE =155, - SC_BLADESTOP_WAIT =156, - SC_BLADESTOP =157, - SC_EXTREMITYFIST =158, - SC_GRAFFITI =159, - - SC_LULLABY =160, - SC_RICHMANKIM =161, - SC_ETERNALCHAOS =162, - SC_DRUMBATTLE =163, - SC_NIBELUNGEN =164, - SC_ROKISWEIL =165, - SC_INTOABYSS =166, - SC_SIEGFRIED =167, - SC_DISSONANCE =168, - SC_WHISTLE =169, - SC_ASSNCROS =170, - SC_POEMBRAGI =171, - SC_APPLEIDUN =172, - SC_UGLYDANCE =173, - SC_HUMMING =174, - SC_DONTFORGETME =175, - SC_FORTUNE =176, - SC_SERVICE4U =177, - - SC_SPIDERWEB =180, /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ - SC_MEMORIZE =181, /* ƒƒ‚ƒ‰ƒCƒY */ -// SC_DPOISON =182, /* –Ò“Å */ - -// SC_EDP =183, /* ƒGƒtƒFƒNƒg‚ª”»–¾‚µ‚½‚çˆÚ“® */ - - SC_WEDDING =187, //Œ‹¥—p(Œ‹¥ˆßւɂȂÁ‚Ä?‚‚Ì‚ª?‚¢‚Æ‚©) - SC_NOCHAT =188, //ÔƒGƒ‚?‘Ô - SC_SPLASHER =189, /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ? */ - SC_SELFDESTRUCTION =190, /* Ž©”š */ - - -// Used by English Team - SC_BROKNARMOR =32, - SC_BROKNWEAPON =33, - SC_SLOWDOWN =45, // for skill slowdown - SC_SIGHTTRASHER =73, -// SC_BASILICA =125, // 125 is the same id as joint break - SC_BASILICA =102, // temporarily use this before an actual id is found [celest] - SC_EDP =114, // - SC_MARIONETTE2 =122, // Marionette target - SC_ENSEMBLE =159, - SC_FOGWALL =178, - SC_GOSPEL =179, - SC_LANDPROTECTOR =182, - SC_ADAPTATION =183, - SC_CHASEWALK =184, - SC_ATKPOT =185, // [Valaris] - SC_MATKPOT =186, // [Valaris] - SC_MINDBREAKER =191, - SC_SPELLBREAKER =192, - SC_DPOISON =193, /* –Ò“Å */ - SC_BLOCKSKILL =194, // for disallowing the use of a skill for a time period - -// [Celest] - SC_BLEEDING = 124, // Temporarily same id as headcrush - SC_MOONLIT = 195, - SC_LEADERSHIP = 196, - SC_GLORYWOUNDS = 197, - SC_SOULCOLD = 198, - SC_HAWKEYES = 199, - SC_BATTLEORDERS = 200, - SC_REGENERATION = 201, - SC_PRESERVE = 202, - -// -- testing various SC effects -// SC_AURABLADE =81, -// SC_CONCENTRATION =83, -// SC_TENSIONRELAX =84, -// SC_BERSERK =85, -// SC_CALLSPIRITS =100, -// SC_PARRYING =100, -// SC_FREECAST =101, -// SC_ABSORBSPIRIT =102, -// SC_ASSUMPTIO =114, -// SC_SHARPSHOOT =127, -// SC_GANGSTER =184, -// SC_CANNIBALIZE =186, -// SC_SPHEREMINE =187, -// SC_METEOSTORM =189, -// SC_CASTCANCEL =190, -// SC_SPIDERWEB =191, -}; -extern int SkillStatusChangeTable[]; - enum { NV_BASIC = 1, @@ -737,6 +566,22 @@ enum { NPC_SELFDESTRUCTION2 = 331, ITM_TOMAHAWK = 337, NPC_DARKCROSS = 338, + NPC_DARKGRANDCROSS, + NPC_DARKSOULSTRIKE, + NPC_DARKJUPITEL, + // temporary names for mob skills [Celest] + NPC_BIND, + NPC_BREAKWEAPON, + NPC_BREAKARMOR, + NPC_BREAKHELM, + NPC_BREAKSHIELD, + NPC_UNDEADATTACK, + + NPC_RUNAWAY = 348, + NPC_EXPLOSIONSPIRITS, + NPC_INCAGI, + + NPC_RECALL = 354, LK_AURABLADE = 355, LK_PARRYING, @@ -794,7 +639,8 @@ enum { WE_BABY, WE_CALLPARENT, WE_CALLBABY, - TK_RUN, + + TK_RUN = 411, TK_READYSTORM, TK_STORMKICK, TK_READYDOWN, diff --git a/src/map/status.c b/src/map/status.c new file mode 100644 index 000000000..a9967d956 --- /dev/null +++ b/src/map/status.c @@ -0,0 +1,5159 @@ + +// ƒXƒe[ƒ^ƒXŒvŽZAó‘ÔˆÙ툗 +#include <time.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <memory.h> + +#include "pc.h" +#include "map.h" +#include "pet.h" +#include "mob.h" +#include "clif.h" +#include "guild.h" +#include "skill.h" +#include "itemdb.h" +#include "battle.h" +#include "chrif.h" +#include "status.h" + +#include "timer.h" +#include "nullpo.h" +#include "script.h" +#include "showmsg.h" + +/* ƒXƒLƒ‹”Ô?„ƒXƒe?ƒ^ƒXˆÙí”Ô??Š·ƒe?ƒuƒ‹ */ +int SkillStatusChangeTable[]={ /* status.h‚Ìenum‚ÌSC_***‚Æ‚ ‚킹‚邱‚Æ */ +/* 0- */ + -1,-1,-1,-1,-1,-1, + SC_PROVOKE, /* ƒvƒƒ{ƒbƒN */ + -1, 1,-1, +/* 10- */ + SC_SIGHT, /* ƒTƒCƒg */ + -1, + SC_SAFETYWALL, /* ƒZ[ƒtƒeƒB[ƒEƒH[ƒ‹ */ + -1,-1,-1, + SC_FREEZE, /* ƒtƒƒXƒgƒ_ƒCƒo? */ + SC_STONE, /* ƒXƒg?ƒ“ƒJ?ƒX */ + -1,-1, +/* 20- */ + -1,-1,-1,-1, + SC_RUWACH, /* ƒ‹ƒAƒt */ + SC_PNEUMA, /* ƒjƒ…[ƒ} */ + -1,-1,-1, + SC_INCREASEAGI, /* ‘¬“x?‰Á */ +/* 30- */ + SC_DECREASEAGI, /* ‘¬“xŒ¸ */ + -1, + SC_SIGNUMCRUCIS, /* ƒVƒOƒiƒ€ƒNƒ‹ƒVƒX */ + SC_ANGELUS, /* ƒGƒ“ƒWƒFƒ‰ƒX */ + SC_BLESSING, /* ƒuƒŒƒbƒVƒ“ƒO */ + -1,-1,-1,-1,-1, +/* 40- */ + -1,-1,-1,-1,-1, + SC_CONCENTRATE, /* W’†—ÍŒüã */ + -1,-1,-1,-1, +/* 50- */ + -1, + SC_HIDING, /* ƒnƒCƒfƒBƒ“ƒO */ + -1,-1,-1,-1,-1,-1,-1,-1, +/* 60- */ + SC_TWOHANDQUICKEN, /* 2HQ */ + SC_AUTOCOUNTER, + -1,-1,-1,-1, + SC_IMPOSITIO, /* ƒCƒ“ƒ|ƒVƒeƒBƒIƒ}ƒkƒX */ + SC_SUFFRAGIUM, /* ƒTƒtƒ‰ƒMƒEƒ€ */ + SC_ASPERSIO, /* ƒAƒXƒyƒ‹ƒVƒI */ + SC_BENEDICTIO, /* ¹?~•Ÿ */ +/* 70- */ + -1, + SC_SLOWPOISON, + -1, + SC_KYRIE, /* ƒLƒŠƒGƒGƒŒƒCƒ\ƒ“ */ + SC_MAGNIFICAT, /* ƒ}ƒOƒjƒtƒBƒJ?ƒg */ + SC_GLORIA, /* ƒOƒƒŠƒA */ + SC_DIVINA, /* ƒŒƒbƒNƒXƒfƒBƒr?ƒi */ + -1, + SC_AETERNA, /* ƒŒƒbƒNƒXƒG?ƒeƒ‹ƒi */ + -1, +/* 80- */ + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/* 90- */ + -1,-1, + SC_QUAGMIRE, /* ƒNƒ@ƒOƒ}ƒCƒA */ + -1,-1,-1,-1,-1,-1,-1, +/* 100- */ + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/* 110- */ + -1, + SC_ADRENALINE, /* ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… */ + SC_WEAPONPERFECTION,/* ƒEƒFƒ|ƒ“ƒp?ƒtƒFƒNƒVƒ‡ƒ“ */ + SC_OVERTHRUST, /* ƒI?ƒo?ƒgƒ‰ƒXƒg */ + SC_MAXIMIZEPOWER, /* ƒ}ƒLƒVƒ}ƒCƒYƒpƒ? */ + -1,-1,-1,-1,-1, +/* 120- */ + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/* 130- */ + -1,-1,-1,-1,-1, + SC_CLOAKING, /* ƒNƒ?ƒLƒ“ƒO */ + SC_STAN, /* ƒ\ƒjƒbƒNƒuƒ? */ + -1, + SC_ENCPOISON, /* ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“ */ + SC_POISONREACT, /* ƒ|ƒCƒYƒ“ƒŠƒAƒNƒg */ +/* 140- */ + SC_POISON, /* ƒxƒmƒ€ƒ_ƒXƒg */ + SC_SPLASHER, /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ? */ + -1, + SC_TRICKDEAD, /* Ž€‚ñ‚¾‚Ó‚è */ + -1,-1,SC_AUTOBERSERK,-1,-1,-1, +/* 150- */ + -1,-1,-1,-1,-1, + SC_LOUD, /* ƒ‰ƒEƒhƒ{ƒCƒX */ + -1, + SC_ENERGYCOAT, /* ƒGƒiƒW?ƒR?ƒg */ + -1,-1, +/* 160- */ + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1, + SC_SELFDESTRUCTION, + -1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, + SC_KEEPING, + -1,-1, + SC_BARRIER, + -1,-1, + SC_HALLUCINATION, + -1,-1, +/* 210- */ + -1,-1,-1,-1,-1, + SC_STRIPWEAPON, + SC_STRIPSHIELD, + SC_STRIPARMOR, + SC_STRIPHELM, + -1, +/* 220- */ + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/* 230- */ + -1,-1,-1,-1, + SC_CP_WEAPON, + SC_CP_SHIELD, + SC_CP_ARMOR, + SC_CP_HELM, + -1,-1, +/* 240- */ + -1,-1,-1,-1,-1,-1,-1,-1,-1, + SC_AUTOGUARD, +/* 250- */ + -1,-1, + SC_REFLECTSHIELD, + -1,-1, + SC_DEVOTION, + SC_PROVIDENCE, + SC_DEFENDER, + SC_SPEARSQUICKEN, + -1, +/* 260- */ + -1,-1,-1,-1,-1,-1,-1,-1, + SC_STEELBODY, + SC_BLADESTOP_WAIT, +/* 270- */ + SC_EXPLOSIONSPIRITS, + SC_EXTREMITYFIST, + -1,-1,-1,-1, + SC_MAGICROD, + -1,-1,-1, +/* 280- */ + SC_FLAMELAUNCHER, + SC_FROSTWEAPON, + SC_LIGHTNINGLOADER, + SC_SEISMICWEAPON, + -1, + SC_VOLCANO, + SC_DELUGE, + SC_VIOLENTGALE, + SC_LANDPROTECTOR, + -1, +/* 290- */ + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/* 300- */ + -1,-1,-1,-1,-1,-1, + SC_LULLABY, + SC_RICHMANKIM, + SC_ETERNALCHAOS, + SC_DRUMBATTLE, +/* 310- */ + SC_NIBELUNGEN, + SC_ROKISWEIL, + SC_INTOABYSS, + SC_SIEGFRIED, + -1,-1,-1, + SC_DISSONANCE, + -1, + SC_WHISTLE, +/* 320- */ + SC_ASSNCROS, + SC_POEMBRAGI, + SC_APPLEIDUN, + -1,-1, + SC_UGLYDANCE, + -1, + SC_HUMMING, + SC_DONTFORGETME, + SC_FORTUNE, +/* 330- */ + SC_SERVICE4U, + SC_SELFDESTRUCTION, + -1,-1,-1,-1,-1,-1,-1,-1, +/* 340- */ + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/* 350- */ + -1,-1,-1,-1,-1, + SC_AURABLADE, + SC_PARRYING, + SC_CONCENTRATION, + SC_TENSIONRELAX, + SC_BERSERK, +/* 360- */ + SC_BERSERK, + SC_ASSUMPTIO, + SC_BASILICA, + -1,-1,-1, + SC_MAGICPOWER, + -1, + SC_SACRIFICE, + SC_GOSPEL, +/* 370- */ + -1,-1,-1,-1,-1,-1,-1,-1, + SC_EDP, + -1, +/* 380- */ + SC_TRUESIGHT, + -1,-1, + SC_WINDWALK, + SC_MELTDOWN, + -1,-1, + SC_CARTBOOST, + -1, + SC_CHASEWALK, +/* 390- */ + SC_REJECTSWORD, + -1,-1,-1,-1, + SC_MOONLIT, + SC_MARIONETTE, + -1, + SC_BLEEDING, + SC_JOINTBEAT, +/* 400 */ + -1,-1, + SC_MINDBREAKER, + SC_MEMORIZE, + SC_FOGWALL, + SC_SPIDERWEB, + -1,-1, + SC_BABY, + -1, +/* 410- */ + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +}; + +static int max_weight_base[MAX_PC_CLASS]; +static int hp_coefficient[MAX_PC_CLASS]; +static int hp_coefficient2[MAX_PC_CLASS]; +static int hp_sigma_val[MAX_PC_CLASS][MAX_LEVEL]; +static int sp_coefficient[MAX_PC_CLASS]; +static int aspd_base[MAX_PC_CLASS][20]; +static int refinebonus[5][3]; // ¸˜Bƒ{[ƒiƒXƒe[ƒuƒ‹(refine_db.txt) +int percentrefinery[5][10]; // ¸˜B¬Œ÷—¦(refine_db.txt) +static int atkmods[3][20]; // •ŠíATKƒTƒCƒYC³(size_fix.txt) +static char job_bonus[3][MAX_PC_CLASS][MAX_LEVEL]; + +int current_equip_item_index; //Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus] +//we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only +//to avoid cards exploits + +/*========================================== + * ¸˜Bƒ{[ƒiƒX + *------------------------------------------ + */ +int status_getrefinebonus(int lv,int type) +{ + if (lv >= 0 && lv < 5 && type >= 0 && type < 3) + return refinebonus[lv][type]; + return 0; +} + +/*========================================== + * ¸˜B¬Œ÷—¦ + *------------------------------------------ + */ +int status_percentrefinery(struct map_session_data *sd,struct item *item) +{ + int percent; + + nullpo_retr(0, item); + percent=percentrefinery[itemdb_wlv(item->nameid)][(int)item->refine]; + + percent += pc_checkskill(sd,BS_WEAPONRESEARCH); // •ŠíŒ¤‹†ƒXƒLƒ‹ŠŽ + + // Šm—¦‚Ì—LŒø”͈̓`ƒFƒbƒN + if( percent > 100 ){ + percent = 100; + } + if( percent < 0 ){ + percent = 0; + } + + return percent; +} + +/*========================================== + * ƒpƒ‰ƒ[ƒ^ŒvŽZ + * first==0‚ÌŽžAŒvŽZ‘Îۂ̃pƒ‰ƒ[ƒ^‚ªŒÄ‚Ño‚µ‘O‚©‚ç + * •Ï ‰»‚µ‚½ê‡Ž©“®‚Åsend‚·‚邪A + * ”\“®“I‚ɕω»‚³‚¹‚½ƒpƒ‰ƒ[ƒ^‚ÍŽ©‘O‚Åsend‚·‚邿‚¤‚É + *------------------------------------------ + */ + +int status_calc_pc(struct map_session_data* sd,int first) +{ + int b_speed,b_max_hp,b_max_sp,b_hp,b_sp,b_weight,b_max_weight,b_paramb[6],b_parame[6],b_hit,b_flee; + int b_aspd,b_watk,b_def,b_watk2,b_def2,b_flee2,b_critical,b_attackrange,b_matk1,b_matk2,b_mdef,b_mdef2,b_class; + int b_base_atk; + struct skill b_skill[MAX_SKILL]; + int i,bl,index; + int skill,aspd_rate,wele,wele_,def_ele,refinedef=0; + int pele=0,pdef_ele=0; + int str,dstr,dex; + struct pc_base_job s_class; + + nullpo_retr(0, sd); + + //?¶‚â—{Žq‚Ìꇂ̌³‚ÌE‹Æ‚ðŽZo‚·‚é + s_class = pc_calc_base_job(sd->status.class_); + + b_speed = sd->speed; + b_max_hp = sd->status.max_hp; + b_max_sp = sd->status.max_sp; + b_hp = sd->status.hp; + b_sp = sd->status.sp; + b_weight = sd->weight; + b_max_weight = sd->max_weight; + memcpy(b_paramb,&sd->paramb,sizeof(b_paramb)); + memcpy(b_parame,&sd->paramc,sizeof(b_parame)); + memcpy(b_skill,&sd->status.skill,sizeof(b_skill)); + b_hit = sd->hit; + b_flee = sd->flee; + b_aspd = sd->aspd; + b_watk = sd->watk; + b_def = sd->def; + b_watk2 = sd->watk2; + b_def2 = sd->def2; + b_flee2 = sd->flee2; + b_critical = sd->critical; + b_attackrange = sd->attackrange; + b_matk1 = sd->matk1; + b_matk2 = sd->matk2; + b_mdef = sd->mdef; + b_mdef2 = sd->mdef2; + b_class = sd->view_class; + sd->view_class = sd->status.class_; + b_base_atk = sd->base_atk; + + pc_calc_skilltree(sd); // ƒXƒLƒ‹ƒcƒŠ?‚ÌŒvŽZ + + sd->max_weight = max_weight_base[s_class.job]+sd->status.str*300; + + if(first&1) { + sd->weight=0; + for(i=0;i<MAX_INVENTORY;i++){ + if(sd->status.inventory[i].nameid==0 || sd->inventory_data[i] == NULL) + continue; + sd->weight += sd->inventory_data[i]->weight*sd->status.inventory[i].amount; + } + sd->cart_max_weight=battle_config.max_cart_weight; + sd->cart_weight=0; + sd->cart_max_num=MAX_CART; + sd->cart_num=0; + for(i=0;i<MAX_CART;i++){ + if(sd->status.cart[i].nameid==0) + continue; + sd->cart_weight+=itemdb_weight(sd->status.cart[i].nameid)*sd->status.cart[i].amount; + sd->cart_num++; + } + } + + memset(sd->paramb,0,sizeof(sd->paramb)); + memset(sd->parame,0,sizeof(sd->parame)); + sd->hit = 0; + sd->flee = 0; + sd->flee2 = 0; + sd->critical = 0; + sd->aspd = 0; + sd->watk = 0; + sd->def = 0; + sd->mdef = 0; + sd->watk2 = 0; + sd->def2 = 0; + sd->mdef2 = 0; + sd->status.max_hp = 0; + sd->status.max_sp = 0; + sd->attackrange = 0; + sd->attackrange_ = 0; + sd->atk_ele = 0; + sd->def_ele = 0; + sd->star =0; + sd->overrefine =0; + sd->matk1 =0; + sd->matk2 =0; + sd->speed = DEFAULT_WALK_SPEED ; + sd->hprate=battle_config.hp_rate; + sd->sprate=battle_config.sp_rate; + sd->castrate=100; + sd->delayrate=100; + sd->dsprate=100; + sd->base_atk=0; + sd->arrow_atk=0; + sd->arrow_ele=0; + sd->arrow_hit=0; + sd->arrow_range=0; + sd->nhealhp=sd->nhealsp=sd->nshealhp=sd->nshealsp=sd->nsshealhp=sd->nsshealsp=0; + memset(sd->addele,0,sizeof(sd->addele)); + memset(sd->addrace,0,sizeof(sd->addrace)); + memset(sd->addsize,0,sizeof(sd->addsize)); + memset(sd->addele_,0,sizeof(sd->addele_)); + memset(sd->addrace_,0,sizeof(sd->addrace_)); + memset(sd->addsize_,0,sizeof(sd->addsize_)); + memset(sd->subele,0,sizeof(sd->subele)); + memset(sd->subrace,0,sizeof(sd->subrace)); + memset(sd->addeff,0,sizeof(sd->addeff)); + memset(sd->addeff2,0,sizeof(sd->addeff2)); + memset(sd->reseff,0,sizeof(sd->reseff)); + memset(&sd->special_state,0,sizeof(sd->special_state)); + memset(sd->weapon_coma_ele,0,sizeof(sd->weapon_coma_ele)); + memset(sd->weapon_coma_race,0,sizeof(sd->weapon_coma_race)); + memset(sd->weapon_atk,0,sizeof(sd->weapon_atk)); + memset(sd->weapon_atk_rate,0,sizeof(sd->weapon_atk_rate)); + + sd->watk_ = 0; //“ñ“—¬—p(?) + sd->watk_2 = 0; + sd->atk_ele_ = 0; + sd->star_ = 0; + sd->overrefine_ = 0; + + sd->aspd_rate = 100; + sd->speed_rate = 100; + sd->hprecov_rate = 100; + sd->sprecov_rate = 100; + sd->critical_def = 0; + sd->double_rate = 0; + sd->near_attack_def_rate = sd->long_attack_def_rate = 0; + sd->atk_rate = sd->matk_rate = 100; + sd->ignore_def_ele = sd->ignore_def_race = 0; + sd->ignore_def_ele_ = sd->ignore_def_race_ = 0; + sd->ignore_mdef_ele = sd->ignore_mdef_race = 0; + sd->arrow_cri = 0; + sd->magic_def_rate = sd->misc_def_rate = 0; + memset(sd->arrow_addele,0,sizeof(sd->arrow_addele)); + memset(sd->arrow_addrace,0,sizeof(sd->arrow_addrace)); + memset(sd->arrow_addsize,0,sizeof(sd->arrow_addsize)); + memset(sd->arrow_addeff,0,sizeof(sd->arrow_addeff)); + memset(sd->arrow_addeff2,0,sizeof(sd->arrow_addeff2)); + memset(sd->magic_addele,0,sizeof(sd->magic_addele)); + memset(sd->magic_addrace,0,sizeof(sd->magic_addrace)); + memset(sd->magic_subrace,0,sizeof(sd->magic_subrace)); + sd->perfect_hit = 0; + sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100; + sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100; + sd->def_ratio_atk_ele = sd->def_ratio_atk_ele_ = 0; + sd->def_ratio_atk_race = sd->def_ratio_atk_race_ = 0; + sd->get_zeny_num = 0; + sd->add_damage_class_count = sd->add_damage_class_count_ = sd->add_magic_damage_class_count = 0; + sd->add_def_class_count = sd->add_mdef_class_count = 0; + sd->monster_drop_item_count = 0; + memset(sd->add_damage_classrate,0,sizeof(sd->add_damage_classrate)); + memset(sd->add_damage_classrate_,0,sizeof(sd->add_damage_classrate_)); + memset(sd->add_magic_damage_classrate,0,sizeof(sd->add_magic_damage_classrate)); + memset(sd->add_def_classrate,0,sizeof(sd->add_def_classrate)); + memset(sd->add_mdef_classrate,0,sizeof(sd->add_mdef_classrate)); + memset(sd->monster_drop_race,0,sizeof(sd->monster_drop_race)); + memset(sd->monster_drop_itemrate,0,sizeof(sd->monster_drop_itemrate)); + sd->speed_add_rate = sd->aspd_add_rate = 100; + sd->double_add_rate = sd->perfect_hit_add = sd->get_zeny_add_num = 0; + sd->splash_range = sd->splash_add_range = 0; + sd->autospell_id = sd->autospell_lv = sd->autospell_rate = 0; + sd->hp_drain_rate = sd->hp_drain_per = sd->sp_drain_rate = sd->sp_drain_per = 0; + sd->hp_drain_rate_ = sd->hp_drain_per_ = sd->sp_drain_rate_ = sd->sp_drain_per_ = 0; + sd->short_weapon_damage_return = sd->long_weapon_damage_return = 0; + sd->magic_damage_return = 0; //AppleGirl Was Here + sd->random_attack_increase_add = sd->random_attack_increase_per = 0; + sd->hp_drain_value = sd->hp_drain_value_ = sd->sp_drain_value = sd->sp_drain_value_ = 0; + sd->unbreakable_equip = 0; + + sd->break_weapon_rate = sd->break_armor_rate = 0; + sd->add_steal_rate = 0; + sd->crit_atk_rate = 0; + sd->no_regen = 0; + sd->unstripable_equip = 0; + sd->autospell2_id = sd->autospell2_lv = sd->autospell2_rate = 0; + memset(sd->critaddrace,0,sizeof(sd->critaddrace)); + memset(sd->addeff3,0,sizeof(sd->addeff3)); + memset(sd->addeff3_type,0,sizeof(sd->addeff3_type)); + memset(sd->skillatk,0,sizeof(sd->skillatk)); + sd->add_damage_class_count = sd->add_damage_class_count_ = sd->add_magic_damage_class_count = 0; + sd->add_def_class_count = sd->add_mdef_class_count = 0; + sd->add_damage_class_count2 = 0; + memset(sd->add_damage_classid,0,sizeof(sd->add_damage_classid)); + memset(sd->add_damage_classid_,0,sizeof(sd->add_damage_classid_)); + memset(sd->add_magic_damage_classid,0,sizeof(sd->add_magic_damage_classid)); + memset(sd->add_damage_classrate,0,sizeof(sd->add_damage_classrate)); + memset(sd->add_damage_classrate_,0,sizeof(sd->add_damage_classrate_)); + memset(sd->add_magic_damage_classrate,0,sizeof(sd->add_magic_damage_classrate)); + memset(sd->add_def_classid,0,sizeof(sd->add_def_classid)); + memset(sd->add_def_classrate,0,sizeof(sd->add_def_classrate)); + memset(sd->add_mdef_classid,0,sizeof(sd->add_mdef_classid)); + memset(sd->add_mdef_classrate,0,sizeof(sd->add_mdef_classrate)); + memset(sd->add_damage_classid2,0,sizeof(sd->add_damage_classid2)); + memset(sd->add_damage_classrate2,0,sizeof(sd->add_damage_classrate2)); + sd->sp_gain_value = 0; + sd->ignore_def_mob = sd->ignore_def_mob_ = 0; + sd->hp_loss_rate = sd->hp_loss_value = sd->hp_loss_type = 0; + memset(sd->addrace2,0,sizeof(sd->addrace2)); + memset(sd->addrace2_,0,sizeof(sd->addrace2_)); + sd->hp_gain_value = sd->sp_drain_type = 0; + memset(sd->subsize,0,sizeof(sd->subsize)); + memset(sd->unequip_losehp,0,sizeof(sd->unequip_losehp)); + memset(sd->unequip_losesp,0,sizeof(sd->unequip_losesp)); + memset(sd->subrace2,0,sizeof(sd->subrace2)); + memset(sd->expaddrace,0,sizeof(sd->expaddrace)); + memset(sd->sp_gain_race,0,sizeof(sd->sp_gain_race)); + + if(!sd->disguiseflag && sd->disguise) { + sd->disguise=0; + clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); + clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); + clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); + clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); + clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); + clif_clearchar(&sd->bl, 9); + pc_setpos(sd, sd->mapname, sd->bl.x, sd->bl.y, 3); + } + + if (sd->status.guild_id > 0) { + struct guild *g = guild_search(sd->status.guild_id); + if (g && strcmp(sd->status.name,g->master)==0) + sd->state.gmaster_flag = (int)g; + } + + for(i=0;i<10;i++) { + current_equip_item_index = index = sd->equip_index[i]; //We pass INDEX to current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus] + if(index < 0) + continue; + if(i == 9 && sd->equip_index[8] == index) + continue; + if(i == 5 && sd->equip_index[4] == index) + continue; + if(i == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index)) + continue; + + if(sd->inventory_data[index]) { + if(sd->inventory_data[index]->type == 4) { + if(sd->status.inventory[index].card[0]!=0x00ff && sd->status.inventory[index].card[0]!=0x00fe && sd->status.inventory[index].card[0]!=(short)0xff00) { + int j; + for(j=0;j<sd->inventory_data[index]->slot;j++){ // ƒJ?ƒh + int c=sd->status.inventory[index].card[j]; + if(c>0){ + if(i == 8 && sd->status.inventory[index].equip == 0x20) + sd->state.lr_flag = 1; + run_script(itemdb_equipscript(c),0,sd->bl.id,0); + sd->state.lr_flag = 0; + } + } + } + } + else if(sd->inventory_data[index]->type==5){ // –h‹ï + if(sd->status.inventory[index].card[0]!=0x00ff && sd->status.inventory[index].card[0]!=0x00fe && sd->status.inventory[index].card[0]!=(short)0xff00) { + int j; + for(j=0;j<sd->inventory_data[index]->slot;j++){ // ƒJ?ƒh + int c=sd->status.inventory[index].card[j]; + if(c>0) + run_script(itemdb_equipscript(c),0,sd->bl.id,0); + } + } + } + } + } + wele = sd->atk_ele; + wele_ = sd->atk_ele_; + def_ele = sd->def_ele; + if(sd->status.pet_id > 0) { + struct pet_data *pd=sd->pd; + if((pd && battle_config.pet_status_support==1) && (battle_config.pet_equip_required==0 || (battle_config.pet_equip_required && pd->equip > 0))) { + if(sd->status.pet_id > 0 && sd->petDB && sd->pet.intimate > 0 && + pd->state.skillbonus == 1) { + pc_bonus(sd,pd->skillbonustype,pd->skillbonusval); +// run_script(sd->petDB->script,0,sd->bl.id,0); + } + pele = sd->atk_ele; + pdef_ele = sd->def_ele; + sd->atk_ele = sd->def_ele = 0; + } + } + memcpy(sd->paramcard,sd->parame,sizeof(sd->paramcard)); + + // ?”õ•i‚É‚æ‚éƒXƒe?ƒ^ƒX?‰»‚Í‚±‚±‚Å?s + for(i=0;i<10;i++) { + current_equip_item_index = index = sd->equip_index[i]; //We pass INDEX to current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus] + if(index < 0) + continue; + if(i == 9 && sd->equip_index[8] == index) + continue; + if(i == 5 && sd->equip_index[4] == index) + continue; + if(i == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index)) + continue; + if(sd->inventory_data[index]) { + sd->def += sd->inventory_data[index]->def; + if(sd->inventory_data[index]->type == 4) { + int r,wlv = sd->inventory_data[index]->wlv; + if(i == 8 && sd->status.inventory[index].equip == 0x20) { + //“ñ“—¬—pƒf?ƒ^“ü—Í + sd->watk_ += sd->inventory_data[index]->atk; + sd->watk_2 = (r=sd->status.inventory[index].refine)* // ¸?U?—Í + refinebonus[wlv][0]; + if( (r-=refinebonus[wlv][2])>0 ) // ‰ß?¸?ƒ{?ƒiƒX + sd->overrefine_ = r*refinebonus[wlv][1]; + + if(sd->status.inventory[index].card[0]==0x00ff){ // »‘¢•Ší + sd->star_ = (sd->status.inventory[index].card[1]>>8); // ¯‚Ì‚©‚¯‚ç + wele_= (sd->status.inventory[index].card[1]&0x0f); // ? « + } + sd->attackrange_ += sd->inventory_data[index]->range; + sd->state.lr_flag = 1; + run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); + sd->state.lr_flag = 0; + } + else { //“ñ“—¬•ŠíˆÈŠO + sd->watk += sd->inventory_data[index]->atk; + sd->watk2 += (r=sd->status.inventory[index].refine)* // ¸?U?—Í + refinebonus[wlv][0]; + if( (r-=refinebonus[wlv][2])>0 ) // ‰ß?¸?ƒ{?ƒiƒX + sd->overrefine += r*refinebonus[wlv][1]; + + if(sd->status.inventory[index].card[0]==0x00ff){ // »‘¢•Ší + sd->star += (sd->status.inventory[index].card[1]>>8); // ¯‚Ì‚©‚¯‚ç + wele = (sd->status.inventory[index].card[1]&0x0f); // ? « + } + sd->attackrange += sd->inventory_data[index]->range; + run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); + } + } + else if(sd->inventory_data[index]->type == 5) { + sd->watk += sd->inventory_data[index]->atk; + refinedef += sd->status.inventory[index].refine*refinebonus[0][0]; + run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); + } + } + } + + if(sd->equip_index[10] >= 0){ // –î + index = sd->equip_index[10]; + if(sd->inventory_data[index]){ //‚Ü‚¾?«‚ª“ü‚Á‚Ä‚¢‚È‚¢ + sd->state.lr_flag = 2; + run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); + sd->state.lr_flag = 0; + sd->arrow_atk += sd->inventory_data[index]->atk; + } + } + sd->def += (refinedef+50)/100; + + if(sd->attackrange < 1) sd->attackrange = 1; + if(sd->attackrange_ < 1) sd->attackrange_ = 1; + if(sd->attackrange < sd->attackrange_) + sd->attackrange = sd->attackrange_; + if(sd->status.weapon == 11) + sd->attackrange += sd->arrow_range; + if(wele > 0) + sd->atk_ele = wele; + if(wele_ > 0) + sd->atk_ele_ = wele_; + if(def_ele > 0) + sd->def_ele = def_ele; + if(battle_config.pet_status_support) { + if(pele > 0 && !sd->atk_ele) + sd->atk_ele = pele; + if(pdef_ele > 0 && !sd->def_ele) + sd->def_ele = pdef_ele; + } + sd->double_rate += sd->double_add_rate; + sd->perfect_hit += sd->perfect_hit_add; + sd->get_zeny_num += sd->get_zeny_add_num; + sd->splash_range += sd->splash_add_range; + if(sd->speed_add_rate != 100) + sd->speed_rate += sd->speed_add_rate - 100; + if(sd->aspd_add_rate != 100) + sd->aspd_rate += sd->aspd_add_rate - 100; + + // •ŠíATKƒTƒCƒY•â³ (‰EŽè) + sd->atkmods[0] = atkmods[0][sd->weapontype1]; + sd->atkmods[1] = atkmods[1][sd->weapontype1]; + sd->atkmods[2] = atkmods[2][sd->weapontype1]; + //•ŠíATKƒTƒCƒY•â³ (¶Žè) + sd->atkmods_[0] = atkmods[0][sd->weapontype2]; + sd->atkmods_[1] = atkmods[1][sd->weapontype2]; + sd->atkmods_[2] = atkmods[2][sd->weapontype2]; + + // jobƒ{?ƒiƒX•ª + for(i=0;i<sd->status.job_level && i<MAX_LEVEL;i++){ + if(job_bonus[s_class.upper][s_class.job][i]) + sd->paramb[job_bonus[s_class.upper][s_class.job][i]-1]++; + } + + if( (skill=pc_checkskill(sd,MC_INCCARRY))>0 ) // skill can be used with an item now, thanks to orn [Valaris] + sd->max_weight += skill*2000; + + if( (skill=pc_checkskill(sd,AC_OWL))>0 ) // ‚Ó‚‚낤‚Ì–Ú + sd->paramb[4] += skill; + + if((skill=pc_checkskill(sd,BS_HILTBINDING))>0) { // Hilt binding gives +1 str +4 atk + sd->paramb[0] ++; + sd->base_atk += 4; + } + if((skill=pc_checkskill(sd,SA_DRAGONOLOGY))>0 ){ // Dragonology increases +1 int every 2 levels + sd->paramb[3] += (int) ((skill+1)*0.5); + } + + // ƒXƒe?ƒ^ƒX?‰»‚É‚æ‚éŠî–{ƒpƒ‰ƒ?ƒ^•â³ + if(sd->sc_count){ + if(sd->sc_data[SC_CONCENTRATE].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1){ // W’†—ÍŒüã + sd->paramb[1]+= (sd->status.agi+sd->paramb[1]+sd->parame[1]-sd->paramcard[1])*(2+sd->sc_data[SC_CONCENTRATE].val1)/100; + sd->paramb[4]+= (sd->status.dex+sd->paramb[4]+sd->parame[4]-sd->paramcard[4])*(2+sd->sc_data[SC_CONCENTRATE].val1)/100; + } + if(sd->sc_data[SC_INCREASEAGI].timer!=-1){ // ‘¬“x?‰Á + sd->paramb[1]+= 2+sd->sc_data[SC_INCREASEAGI].val1; + sd->speed -= sd->speed *25/100; + } + if(sd->sc_data[SC_DECREASEAGI].timer!=-1) { // ‘¬“xŒ¸(agi‚Íbattle.c‚Å) + sd->speed = sd->speed *125/100; + sd->paramb[1] -= 2 + sd->sc_data[SC_DECREASEAGI].val1; // reduce agility [celest] + } + if(sd->sc_data[SC_CLOAKING].timer!=-1) { + sd->critical_rate += 100; // critical increases + sd->speed = sd->speed * (sd->sc_data[SC_CLOAKING].val3-sd->sc_data[SC_CLOAKING].val1*3) /100; + } + if(sd->sc_data[SC_CHASEWALK].timer!=-1) { + sd->speed = sd->speed * sd->sc_data[SC_CHASEWALK].val3 /100; // slow down by chasewalk + if(sd->sc_data[SC_CHASEWALK].val4) + sd->paramb[0] += (1<<(sd->sc_data[SC_CHASEWALK].val1-1)); // increases strength after 10 seconds + } + if(sd->sc_data[SC_SLOWDOWN].timer!=-1) + sd->speed = sd->speed*150/100; + if(sd->sc_data[SC_SPEEDUP0].timer!=-1 && sd->sc_data[SC_INCREASEAGI].timer==-1) + sd->speed -= sd->speed*25/100; + if(sd->sc_data[SC_BLESSING].timer!=-1){ // ƒuƒŒƒbƒVƒ“ƒO + sd->paramb[0]+= sd->sc_data[SC_BLESSING].val1; + sd->paramb[3]+= sd->sc_data[SC_BLESSING].val1; + sd->paramb[4]+= sd->sc_data[SC_BLESSING].val1; + } + if(sd->sc_data[SC_GLORIA].timer!=-1) // ƒOƒƒŠƒA + sd->paramb[5]+= 30; + if(sd->sc_data[SC_LOUD].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1) // ƒ‰ƒEƒhƒ{ƒCƒX + sd->paramb[0]+= 4; + if(sd->sc_data[SC_QUAGMIRE].timer!=-1){ // ƒNƒ@ƒOƒ}ƒCƒA + //int agib = (sd->status.agi+sd->paramb[1]+sd->parame[1])*(sd->sc_data[SC_QUAGMIRE].val1*10)/100; + //int dexb = (sd->status.dex+sd->paramb[4]+sd->parame[4])*(sd->sc_data[SC_QUAGMIRE].val1*10)/100; + //sd->paramb[1]-= agib > 50 ? 50 : agib; + //sd->paramb[4]-= dexb > 50 ? 50 : dexb; + sd->paramb[1]-= sd->sc_data[SC_QUAGMIRE].val1*5; + sd->paramb[4]-= sd->sc_data[SC_QUAGMIRE].val1*5; + sd->speed = sd->speed*3/2; + } + if(sd->sc_data[SC_TRUESIGHT].timer!=-1){ // ƒgƒDƒ‹?ƒTƒCƒg + sd->paramb[0]+= 5; + sd->paramb[1]+= 5; + sd->paramb[2]+= 5; + sd->paramb[3]+= 5; + sd->paramb[4]+= 5; + sd->paramb[5]+= 5; + } + if(sd->sc_data[SC_MARIONETTE].timer!=-1){ + // skip partner checking -- should be handled in status_change_timer + //struct map_session_data *psd = map_id2sd(sd->sc_data[SC_MARIONETTE2].val3); + //if (psd) { // if partner is found + sd->paramb[0]-= sd->status.str/2; // bonuses not included + sd->paramb[1]-= sd->status.agi/2; + sd->paramb[2]-= sd->status.vit/2; + sd->paramb[3]-= sd->status.int_/2; + sd->paramb[4]-= sd->status.dex/2; + sd->paramb[5]-= sd->status.luk/2; + //} + } + else if(sd->sc_data[SC_MARIONETTE2].timer!=-1){ + struct map_session_data *psd = map_id2sd(sd->sc_data[SC_MARIONETTE2].val3); + if (psd) { // if partner is found + sd->paramb[0] += sd->status.str+psd->status.str/2 > 99 ? 99-sd->status.str : psd->status.str/2; + sd->paramb[1] += sd->status.agi+psd->status.agi/2 > 99 ? 99-sd->status.agi : psd->status.agi/2; + sd->paramb[2] += sd->status.vit+psd->status.vit/2 > 99 ? 99-sd->status.vit : psd->status.vit/2; + sd->paramb[3] += sd->status.int_+psd->status.int_/2 > 99 ? 99-sd->status.int_ : psd->status.int_/2; + sd->paramb[4] += sd->status.dex+psd->status.dex/2 > 99 ? 99-sd->status.dex : psd->status.dex/2; + sd->paramb[5] += sd->status.luk+psd->status.luk/2 > 99 ? 99-sd->status.luk : psd->status.luk/2; + } + } + if(sd->sc_data[SC_GOSPEL].timer!=-1 && sd->sc_data[SC_GOSPEL].val4 == BCT_PARTY){ + if (sd->sc_data[SC_GOSPEL].val3 == 6) { + sd->paramb[0]+= 2; + sd->paramb[1]+= 2; + sd->paramb[2]+= 2; + sd->paramb[3]+= 2; + sd->paramb[4]+= 2; + sd->paramb[5]+= 2; + } + } + // New guild skills - Celest + if (sd->sc_data[SC_BATTLEORDERS].timer != -1) { + sd->paramb[0]+= 5; + sd->paramb[3]+= 5; + sd->paramb[4]+= 5; + } + if (sd->sc_data[SC_GUILDAURA].timer != -1) { + if (sd->sc_data[SC_GUILDAURA].val4 & 1<<0) + sd->paramb[0] += 2; + if (sd->sc_data[SC_GUILDAURA].val4 & 1<<1) + sd->paramb[2] += 2; + if (sd->sc_data[SC_GUILDAURA].val4 & 1<<2) + sd->paramb[1] += 2; + if (sd->sc_data[SC_GUILDAURA].val4 & 1<<3) + sd->paramb[4] += 2; + } + } + + //1“x‚àŽ€‚ñ‚łȂ¢Job70ƒXƒpƒmƒr‚É+10 + if(s_class.job == 23 && sd->die_counter == 0 && sd->status.job_level >= 70){ + sd->paramb[0]+= 15; + sd->paramb[1]+= 15; + sd->paramb[2]+= 15; + sd->paramb[3]+= 15; + sd->paramb[4]+= 15; + sd->paramb[5]+= 15; + } + sd->paramc[0]=sd->status.str+sd->paramb[0]+sd->parame[0]; + sd->paramc[1]=sd->status.agi+sd->paramb[1]+sd->parame[1]; + sd->paramc[2]=sd->status.vit+sd->paramb[2]+sd->parame[2]; + sd->paramc[3]=sd->status.int_+sd->paramb[3]+sd->parame[3]; + sd->paramc[4]=sd->status.dex+sd->paramb[4]+sd->parame[4]; + sd->paramc[5]=sd->status.luk+sd->paramb[5]+sd->parame[5]; + for(i=0;i<6;i++) + if(sd->paramc[i] < 0) sd->paramc[i] = 0; + + if (sd->sc_count) { + if (sd->sc_data[SC_CURSE].timer!=-1) + sd->paramc[5] = 0; + } + + if(sd->status.weapon == 11 || sd->status.weapon == 13 || sd->status.weapon == 14) { + str = sd->paramc[4]; + dex = sd->paramc[0]; + } + else { + str = sd->paramc[0]; + dex = sd->paramc[4]; + } + dstr = str/10; + sd->base_atk += str + dstr*dstr + dex/5 + sd->paramc[5]/5; + sd->matk1 += sd->paramc[3]+(sd->paramc[3]/5)*(sd->paramc[3]/5); + sd->matk2 += sd->paramc[3]+(sd->paramc[3]/7)*(sd->paramc[3]/7); + if(sd->matk1 < sd->matk2) { + int temp = sd->matk2; + sd->matk2 = sd->matk1; + sd->matk1 = temp; + } + sd->hit += sd->paramc[4] + sd->status.base_level; + sd->flee += sd->paramc[1] + sd->status.base_level; + sd->def2 += sd->paramc[2]; + sd->mdef2 += sd->paramc[3]; + sd->flee2 += sd->paramc[5]+10; + sd->critical += (sd->paramc[5]*3)+10; + + if(sd->base_atk < 1) + sd->base_atk = 1; + if(sd->critical_rate != 100) + sd->critical = (sd->critical*sd->critical_rate)/100; + if(sd->critical < 10) sd->critical = 10; + if(sd->hit_rate != 100) + sd->hit = (sd->hit*sd->hit_rate)/100; + if(sd->hit < 1) sd->hit = 1; + if(sd->flee_rate != 100) + sd->flee = (sd->flee*sd->flee_rate)/100; + if(sd->flee < 1) sd->flee = 1; + if(sd->flee2_rate != 100) + sd->flee2 = (sd->flee2*sd->flee2_rate)/100; + if(sd->flee2 < 10) sd->flee2 = 10; + if(sd->def_rate != 100) + sd->def = (sd->def*sd->def_rate)/100; + if(sd->def < 0) sd->def = 0; + if(sd->def2_rate != 100) + sd->def2 = (sd->def2*sd->def2_rate)/100; + if(sd->def2 < 1) sd->def2 = 1; + if(sd->mdef_rate != 100) + sd->mdef = (sd->mdef*sd->mdef_rate)/100; + if(sd->mdef < 0) sd->mdef = 0; + if(sd->mdef2_rate != 100) + sd->mdef2 = (sd->mdef2*sd->mdef2_rate)/100; + if(sd->mdef2 < 1) sd->mdef2 = 1; + + // “ñ“—¬ ASPD C³ + if (sd->status.weapon <= 16) + sd->aspd += aspd_base[s_class.job][sd->status.weapon]-(sd->paramc[1]*4+sd->paramc[4])*aspd_base[s_class.job][sd->status.weapon]/1000; + else + sd->aspd += ( + (aspd_base[s_class.job][sd->weapontype1]-(sd->paramc[1]*4+sd->paramc[4])*aspd_base[s_class.job][sd->weapontype1]/1000) + + (aspd_base[s_class.job][sd->weapontype2]-(sd->paramc[1]*4+sd->paramc[4])*aspd_base[s_class.job][sd->weapontype2]/1000) + ) * 140 / 200; + + aspd_rate = sd->aspd_rate; + + //U?‘¬“x?‰Á + + if((skill=pc_checkskill(sd,AC_VULTURE))>0){ // ƒƒV‚Ì–Ú + sd->hit += skill; + if(sd->status.weapon == 11) + sd->attackrange += skill; + } + + if( (skill=pc_checkskill(sd,BS_WEAPONRESEARCH))>0) // •Ší?‹†‚Ì–½’†—¦?‰Á + sd->hit += skill*2; + if(sd->status.option&2 && (skill = pc_checkskill(sd,RG_TUNNELDRIVE))>0 ) // ƒgƒ“ƒlƒ‹ƒhƒ‰ƒCƒu // ƒgƒ“ƒlƒ‹ƒhƒ‰ƒCƒu + sd->speed += (100-16*skill)*DEFAULT_WALK_SPEED/100; + //sd->speed += (1.2*DEFAULT_WALK_SPEED - skill*9); + if (pc_iscarton(sd) && (skill=pc_checkskill(sd,MC_PUSHCART))>0) // ƒJ?ƒg‚É‚æ‚鑬“x’ቺ + sd->speed += (short) ((10-skill) * (DEFAULT_WALK_SPEED * 0.1)); + else if (pc_isriding(sd)) { // ƒyƒRƒyƒR?‚è‚É‚æ‚鑬“x?‰Á + sd->speed -= (short) ((0.25 * DEFAULT_WALK_SPEED)); + sd->max_weight += 10000; + } + if((skill=pc_checkskill(sd,CR_TRUST))>0) { // ƒtƒFƒCƒX + sd->status.max_hp += skill*200; + sd->subele[6] += skill*5; + } + if((skill=pc_checkskill(sd,BS_SKINTEMPER))>0) { + sd->subele[0] += skill; + sd->subele[3] += skill*5; + } + if((skill=pc_checkskill(sd,SA_ADVANCEDBOOK))>0 ) + aspd_rate -= (int) (skill*0.5); + + bl=sd->status.base_level; + + sd->status.max_hp += (3500 + bl*hp_coefficient2[s_class.job] + hp_sigma_val[s_class.job][(bl > 0)? bl-1:0])/100 * (100 + sd->paramc[2])/100 + (sd->parame[2] - sd->paramcard[2]); + if (s_class.upper==1) // [MouseJstr] + sd->status.max_hp = sd->status.max_hp * 130/100; + else if (s_class.upper==2) + sd->status.max_hp = sd->status.max_hp * 70/100; + + if (sd->hprate <= 0) + sd->hprate = 1; + if(sd->hprate!=100) + sd->status.max_hp = sd->status.max_hp*sd->hprate/100; + + if(sd->sc_count && sd->sc_data[SC_BERSERK].timer!=-1){ // ƒo?ƒT?ƒN + sd->status.max_hp = sd->status.max_hp * 3; + // sd->status.hp = sd->status.hp * 3; + if(sd->status.max_hp > battle_config.max_hp) // removed negative max hp bug by Valaris + sd->status.max_hp = battle_config.max_hp; + if(sd->status.hp > battle_config.max_hp) // removed negative max hp bug by Valaris + sd->status.hp = battle_config.max_hp; + } + if(s_class.job == 23 && sd->status.base_level >= 99){ + sd->status.max_hp = sd->status.max_hp + 2000; + } + + if(sd->status.max_hp > battle_config.max_hp) // removed negative max hp bug by Valaris + sd->status.max_hp = battle_config.max_hp; + if(sd->status.max_hp <= 0) sd->status.max_hp = 1; // end + + // Å‘åSPŒvŽZ + sd->status.max_sp += ((sp_coefficient[s_class.job] * bl) + 1000)/100 * (100 + sd->paramc[3])/100 + (sd->parame[3] - sd->paramcard[3]); + if (s_class.upper==1) // [MouseJstr] + sd->status.max_sp = sd->status.max_sp * 130/100; + else if (s_class.upper==2) + sd->status.max_sp = sd->status.max_sp * 70/100; + if (sd->sprate <= 0) + sd->sprate = 1; + if(sd->sprate!=100) + sd->status.max_sp = sd->status.max_sp*sd->sprate/100; + + if((skill=pc_checkskill(sd,HP_MEDITATIO))>0) // ƒƒfƒBƒeƒCƒeƒBƒI + sd->status.max_sp += sd->status.max_sp*skill/100; + if((skill=pc_checkskill(sd,HW_SOULDRAIN))>0) /* ƒ\ƒEƒ‹ƒhƒŒƒCƒ“ */ + sd->status.max_sp += sd->status.max_sp*2*skill/100; + + if(sd->status.max_sp < 0 || sd->status.max_sp > battle_config.max_sp) + sd->status.max_sp = battle_config.max_sp; + + //Ž©‘R‰ñ•œHP + sd->nhealhp = 1 + (sd->paramc[2]/5) + (sd->status.max_hp/200); + if((skill=pc_checkskill(sd,SM_RECOVERY)) > 0) { /* HP‰ñ•œ—ÍŒüã */ + sd->nshealhp = skill*5 + (sd->status.max_hp*skill/500); + if(sd->nshealhp > 0x7fff) sd->nshealhp = 0x7fff; + } + //Ž©‘R‰ñ•œSP + sd->nhealsp = 1 + (sd->paramc[3]/6) + (sd->status.max_sp/100); + if(sd->paramc[3] >= 120) + sd->nhealsp += ((sd->paramc[3]-120)>>1) + 4; + if((skill=pc_checkskill(sd,MG_SRECOVERY)) > 0) { /* SP‰ñ•œ—ÍŒüã */ + sd->nshealsp = skill*3 + (sd->status.max_sp*skill/500); + if(sd->nshealsp > 0x7fff) sd->nshealsp = 0x7fff; + } + + if((skill = pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0) { + sd->nsshealhp = skill*4 + (sd->status.max_hp*skill/500); + sd->nsshealsp = skill*2 + (sd->status.max_sp*skill/500); + if(sd->nsshealhp > 0x7fff) sd->nsshealhp = 0x7fff; + if(sd->nsshealsp > 0x7fff) sd->nsshealsp = 0x7fff; + } + if(sd->hprecov_rate != 100) { + sd->nhealhp = sd->nhealhp*sd->hprecov_rate/100; + if(sd->nhealhp < 1) sd->nhealhp = 1; + } + if(sd->sprecov_rate != 100) { + sd->nhealsp = sd->nhealsp*sd->sprecov_rate/100; + if(sd->nhealsp < 1) sd->nhealsp = 1; + } + /* if((skill=pc_checkskill(sd,HP_MEDITATIO)) > 0) { // f?fffBfefCfefBfI,I'SPR,A*,I',E`,¡©Z((c)¡®R¢¶n~.©«,E',(c),(c),e' + sd->nhealsp += 3*skill*(sd->status.max_sp)/100; + if(sd->nhealsp > 0x7fff) sd->nhealsp = 0x7fff; + } Increase natural SP regen instead of colossal SP Recovery effect [DracoRPG]*/ + + // Ží‘°‘Ï«i‚±‚ê‚Å‚¢‚¢‚ÌH ƒfƒBƒoƒCƒ“ƒvƒƒeƒNƒVƒ‡ƒ“‚Æ“¯‚¶?—‚ª‚¢‚é‚©‚àj + if( (skill=pc_checkskill(sd,SA_DRAGONOLOGY))>0 ){ // ƒhƒ‰ƒSƒmƒƒW? + skill = skill*4; + sd->addrace[9]+=skill; + sd->addrace_[9]+=skill; + sd->subrace[9]+=skill; + sd->magic_addrace[9]+=skill; + sd->magic_subrace[9]-=skill; + } + + //Flee㸠+ if( (skill=pc_checkskill(sd,TF_MISS))>0 ){ // ‰ñ”ð—¦?‰Á + sd->flee += skill*((sd->status.class_==12 || sd->status.class_==17 || sd->status.class_==4013 || sd->status.class_==4018) ? 4 : 3); + if((sd->status.class_==12 || sd->status.class_==4013) && (sd->sc_count && sd->sc_data[SC_CLOAKING].timer==-1)) + sd->speed -= (short)(skill*1.5/100 * DEFAULT_WALK_SPEED); + } + if( (skill=pc_checkskill(sd,MO_DODGE))>0 ) // Œ©Ø‚è + sd->flee += (skill*3)>>1; + + // ƒXƒLƒ‹‚âƒXƒe?ƒ^ƒXˆÙí‚É‚æ‚é?‚è‚̃pƒ‰ƒ?ƒ^•â³ + if(sd->sc_count){ + // ATK/DEF?‰»Œ` + if(sd->sc_data[SC_ANGELUS].timer!=-1) // ƒGƒ“ƒWƒFƒ‰ƒX + sd->def2 = sd->def2*(110+5*sd->sc_data[SC_ANGELUS].val1)/100; + if(sd->sc_data[SC_IMPOSITIO].timer!=-1) {// ƒCƒ“ƒ|ƒVƒeƒBƒIƒ}ƒkƒX + sd->watk += sd->sc_data[SC_IMPOSITIO].val1*5; + index = sd->equip_index[8]; + if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4) + sd->watk_ += sd->sc_data[SC_IMPOSITIO].val1*5; + } + if(sd->sc_data[SC_PROVOKE].timer!=-1){ // ƒvƒƒ{ƒbƒN + sd->def2 = sd->def2*(100-6*sd->sc_data[SC_PROVOKE].val1)/100; + sd->base_atk = sd->base_atk*(100+2*sd->sc_data[SC_PROVOKE].val1)/100; + sd->watk = sd->watk*(100+2*sd->sc_data[SC_PROVOKE].val1)/100; + index = sd->equip_index[8]; + if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4) + sd->watk_ = sd->watk_*(100+2*sd->sc_data[SC_PROVOKE].val1)/100; + } + if(sd->sc_data[SC_ENDURE].timer!=-1) + sd->mdef2 += sd->sc_data[SC_ENDURE].val1; + if(sd->sc_data[SC_MINDBREAKER].timer!=-1){ // ƒvƒƒ{ƒbƒN + sd->mdef2 = sd->mdef2*(100-6*sd->sc_data[SC_MINDBREAKER].val1)/100; + sd->matk1 = sd->matk1*(100+2*sd->sc_data[SC_MINDBREAKER].val1)/100; + sd->matk2 = sd->matk2*(100+2*sd->sc_data[SC_MINDBREAKER].val1)/100; + } + if(sd->sc_data[SC_POISON].timer!=-1) // “Å?‘Ô + sd->def2 = sd->def2*75/100; + if(sd->sc_data[SC_CURSE].timer!=-1){ + sd->base_atk = sd->base_atk*75/100; + sd->watk = sd->watk*75/100; + index = sd->equip_index[8]; + if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4) + sd->watk_ = sd->watk_*75/100; + } + if(sd->sc_data[SC_DRUMBATTLE].timer!=-1){ // ?‘¾ŒÛ‚Ì‹¿‚« + sd->watk += sd->sc_data[SC_DRUMBATTLE].val2; + sd->def += sd->sc_data[SC_DRUMBATTLE].val3; + index = sd->equip_index[8]; + if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4) + sd->watk_ += sd->sc_data[SC_DRUMBATTLE].val2; + } + if(sd->sc_data[SC_NIBELUNGEN].timer!=-1) { // ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö + index = sd->equip_index[9]; + /*if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 3) + sd->watk += sd->sc_data[SC_NIBELUNGEN].val3; + index = sd->equip_index[8]; + if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 3) + sd->watk_ += sd->sc_data[SC_NIBELUNGEN].val3; + index = sd->equip_index[9];*/ + if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4) + sd->watk2 += sd->sc_data[SC_NIBELUNGEN].val3; + index = sd->equip_index[8]; + if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4) + sd->watk_2 += sd->sc_data[SC_NIBELUNGEN].val3; + } + + if(sd->sc_data[SC_VOLCANO].timer!=-1 && sd->def_ele==3){ // ƒ{ƒ‹ƒP?ƒm + sd->watk += sd->sc_data[SC_VOLCANO].val3; + } + + if(sd->sc_data[SC_SIGNUMCRUCIS].timer!=-1) + sd->def = sd->def * (100 - sd->sc_data[SC_SIGNUMCRUCIS].val2)/100; + if(sd->sc_data[SC_ETERNALCHAOS].timer!=-1) // ƒGƒ^?ƒiƒ‹ƒJƒIƒX + sd->def=0; + + if(sd->sc_data[SC_CONCENTRATION].timer!=-1){ //ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ + sd->watk = sd->watk * (100 + 5*sd->sc_data[SC_CONCENTRATION].val1)/100; + index = sd->equip_index[8]; + if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4) + sd->watk_ = sd->watk * (100 + 5*sd->sc_data[SC_CONCENTRATION].val1)/100; + sd->def = sd->def * (100 - 5*sd->sc_data[SC_CONCENTRATION].val1)/100; + } + + if(sd->sc_data[SC_MAGICPOWER].timer!=-1){ //–‚–@—Í?• + sd->matk1 = sd->matk1*(100+5*sd->sc_data[SC_MAGICPOWER].val1)/100; + sd->matk2 = sd->matk2*(100+5*sd->sc_data[SC_MAGICPOWER].val1)/100; + } + if(sd->sc_data[SC_ATKPOT].timer!=-1) + sd->watk += sd->sc_data[SC_ATKPOT].val1; + if(sd->sc_data[SC_MATKPOT].timer!=-1){ + sd->matk1 += sd->sc_data[SC_MATKPOT].val1; + sd->matk2 += sd->sc_data[SC_MATKPOT].val1; + } + + // ASPD/ˆÚ“®‘¬“x?‰»Œn + if(sd->sc_data[SC_TWOHANDQUICKEN].timer != -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) // 2HQ + aspd_rate -= 30; + if(sd->sc_data[SC_ADRENALINE].timer != -1 && sd->sc_data[SC_TWOHANDQUICKEN].timer == -1 && + sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) { // ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… + if(sd->sc_data[SC_ADRENALINE].val2 || !battle_config.party_skill_penalty) + aspd_rate -= 30; + else + aspd_rate -= 25; + } + if(sd->sc_data[SC_SPEARSQUICKEN].timer != -1 && sd->sc_data[SC_ADRENALINE].timer == -1 && + sd->sc_data[SC_TWOHANDQUICKEN].timer == -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) // ƒXƒsƒAƒNƒBƒbƒPƒ“ + aspd_rate -= sd->sc_data[SC_SPEARSQUICKEN].val2; + if(sd->sc_data[SC_ASSNCROS].timer!=-1 && // —[—z‚̃AƒTƒVƒ“ƒNƒƒX + sd->sc_data[SC_TWOHANDQUICKEN].timer==-1 && sd->sc_data[SC_ADRENALINE].timer==-1 && sd->sc_data[SC_SPEARSQUICKEN].timer==-1 && + sd->sc_data[SC_DONTFORGETME].timer == -1) + aspd_rate -= 5+sd->sc_data[SC_ASSNCROS].val1+sd->sc_data[SC_ASSNCROS].val2+sd->sc_data[SC_ASSNCROS].val3; + if(sd->sc_data[SC_DONTFORGETME].timer!=-1){ // Ž„‚ð–Y‚ê‚È‚¢‚Å + aspd_rate += sd->sc_data[SC_DONTFORGETME].val1*3 + sd->sc_data[SC_DONTFORGETME].val2 + (sd->sc_data[SC_DONTFORGETME].val3>>16); + sd->speed= sd->speed*(100+sd->sc_data[SC_DONTFORGETME].val1*2 + sd->sc_data[SC_DONTFORGETME].val2 + (sd->sc_data[SC_DONTFORGETME].val3&0xffff))/100; + } + if( sd->sc_data[i=SC_SPEEDPOTION3].timer!=-1 || + sd->sc_data[i=SC_SPEEDPOTION2].timer!=-1 || + sd->sc_data[i=SC_SPEEDPOTION1].timer!=-1 || + sd->sc_data[i=SC_SPEEDPOTION0].timer!=-1) // ? ‘¬ƒ|?ƒVƒ‡ƒ“ + aspd_rate -= sd->sc_data[i].val2; + if(sd->sc_data[SC_WINDWALK].timer!=-1 && sd->sc_data[SC_INCREASEAGI].timer==-1) //ƒEƒBƒ“ƒhƒEƒH?ƒNŽbÍLv*2%Œ¸ŽZ + sd->speed -= sd->speed *(sd->sc_data[SC_WINDWALK].val1*2)/100; + if(sd->sc_data[SC_CARTBOOST].timer!=-1) // ƒJ?ƒgƒu?ƒXƒg + sd->speed -= (DEFAULT_WALK_SPEED * 20)/100; + if(sd->sc_data[SC_BERSERK].timer!=-1) //ƒo?ƒT?ƒN’†‚ÍIA‚Æ“¯‚¶‚®‚ç‚¢‘¬‚¢H + sd->speed -= sd->speed *25/100; + if(sd->sc_data[SC_WEDDING].timer!=-1) //Œ‹¥’†‚Í?‚‚Ì‚ª?‚¢ + sd->speed = 2*DEFAULT_WALK_SPEED; + + // HIT/FLEE?‰»Œn + if(sd->sc_data[SC_WHISTLE].timer!=-1){ // Œû“J + sd->flee += sd->flee * (sd->sc_data[SC_WHISTLE].val1 + +sd->sc_data[SC_WHISTLE].val2+(sd->sc_data[SC_WHISTLE].val3>>16))/100; + sd->flee2+= (sd->sc_data[SC_WHISTLE].val1+sd->sc_data[SC_WHISTLE].val2+(sd->sc_data[SC_WHISTLE].val3&0xffff)) * 10; + } + if(sd->sc_data[SC_HUMMING].timer!=-1) // ƒnƒ~ƒ“ƒO + sd->hit += (sd->sc_data[SC_HUMMING].val1*2+sd->sc_data[SC_HUMMING].val2 + +sd->sc_data[SC_HUMMING].val3) * sd->hit/100; + if(sd->sc_data[SC_VIOLENTGALE].timer!=-1 && sd->def_ele==4){ // ƒoƒCƒIƒŒƒ“ƒgƒQƒCƒ‹ + sd->flee += sd->flee*sd->sc_data[SC_VIOLENTGALE].val3/100; + } + if(sd->sc_data[SC_BLIND].timer!=-1){ // ˆÃ? + sd->hit -= sd->hit*25/100; + sd->flee -= sd->flee*25/100; + } + if(sd->sc_data[SC_WINDWALK].timer!=-1) // ƒEƒBƒ“ƒhƒEƒH?ƒN + sd->flee += sd->flee*(sd->sc_data[SC_WINDWALK].val2)/100; + if(sd->sc_data[SC_SPIDERWEB].timer!=-1) //ƒXƒpƒCƒ_?ƒEƒFƒu + sd->flee -= sd->flee*50/100; + if(sd->sc_data[SC_TRUESIGHT].timer!=-1) //ƒgƒDƒ‹?ƒTƒCƒg + sd->hit += 3*(sd->sc_data[SC_TRUESIGHT].val1); + if(sd->sc_data[SC_CONCENTRATION].timer!=-1) //ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ + sd->hit += (10*(sd->sc_data[SC_CONCENTRATION].val1)); + + // ‘Ï« + if(sd->sc_data[SC_SIEGFRIED].timer!=-1){ // •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh + sd->subele[1] += sd->sc_data[SC_SIEGFRIED].val2; // … + sd->subele[2] += sd->sc_data[SC_SIEGFRIED].val2; // … + sd->subele[3] += sd->sc_data[SC_SIEGFRIED].val2; // ‰Î + sd->subele[4] += sd->sc_data[SC_SIEGFRIED].val2; // … + sd->subele[5] += sd->sc_data[SC_SIEGFRIED].val2; // … + sd->subele[6] += sd->sc_data[SC_SIEGFRIED].val2; // … + sd->subele[7] += sd->sc_data[SC_SIEGFRIED].val2; // … + sd->subele[8] += sd->sc_data[SC_SIEGFRIED].val2; // … + sd->subele[9] += sd->sc_data[SC_SIEGFRIED].val2; // … + } + if(sd->sc_data[SC_PROVIDENCE].timer!=-1){ // ƒvƒƒ”ƒBƒfƒ“ƒX + sd->subele[6] += sd->sc_data[SC_PROVIDENCE].val2; // ? ¹?« + sd->subrace[6] += sd->sc_data[SC_PROVIDENCE].val2; // ? ?–‚ + } + + // ‚»‚Ì‘¼ + if(sd->sc_data[SC_APPLEIDUN].timer!=-1){ // ƒCƒhƒDƒ“‚Ì—ÑŒç + sd->status.max_hp += ((5+sd->sc_data[SC_APPLEIDUN].val1*2+((sd->sc_data[SC_APPLEIDUN].val2+1)>>1) + +sd->sc_data[SC_APPLEIDUN].val3/10) * sd->status.max_hp)/100; + if(sd->status.max_hp < 0 || sd->status.max_hp > battle_config.max_hp) + sd->status.max_hp = battle_config.max_hp; + } + if(sd->sc_data[SC_DELUGE].timer!=-1 && sd->def_ele==1){ // ƒfƒŠƒ…?ƒW + sd->status.max_hp += sd->status.max_hp * deluge_eff[sd->sc_data[SC_DELUGE].val1-1]/100; + if(sd->status.max_hp < 0 || sd->status.max_hp > battle_config.max_hp) + sd->status.max_hp = battle_config.max_hp; + } + if(sd->sc_data[SC_SERVICE4U].timer!=-1) { // ƒT?ƒrƒXƒtƒH?ƒ†? + sd->status.max_sp += sd->status.max_sp*(10+sd->sc_data[SC_SERVICE4U].val1+sd->sc_data[SC_SERVICE4U].val2 + +sd->sc_data[SC_SERVICE4U].val3)/100; + if(sd->status.max_sp < 0 || sd->status.max_sp > battle_config.max_sp) + sd->status.max_sp = battle_config.max_sp; + sd->dsprate-=(10+sd->sc_data[SC_SERVICE4U].val1*3+sd->sc_data[SC_SERVICE4U].val2 + +sd->sc_data[SC_SERVICE4U].val3); + if(sd->dsprate<0)sd->dsprate=0; + } + + if(sd->sc_data[SC_FORTUNE].timer!=-1) // K‰^‚̃LƒX + sd->critical += (10+sd->sc_data[SC_FORTUNE].val1+sd->sc_data[SC_FORTUNE].val2 + +sd->sc_data[SC_FORTUNE].val3)*10; + + if(sd->sc_data[SC_EXPLOSIONSPIRITS].timer!=-1){ // ”š—ô”g“® + if(s_class.job==23) + sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val1*100; + else + sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val2; + } + + if(sd->sc_data[SC_STEELBODY].timer!=-1){ // ‹à„ + sd->def = 90; + sd->mdef = 90; + aspd_rate += 25; + sd->speed = (sd->speed * 125) / 100; + } + if(sd->sc_data[SC_DEFENDER].timer != -1) { + //sd->aspd += (550 - sd->sc_data[SC_DEFENDER].val1*50); + aspd_rate += (25 - sd->sc_data[SC_DEFENDER].val1*5); + sd->speed = (sd->speed * (155 - sd->sc_data[SC_DEFENDER].val1*5)) / 100; + } + if(sd->sc_data[SC_ENCPOISON].timer != -1) + sd->addeff[4] += sd->sc_data[SC_ENCPOISON].val2; + + if( sd->sc_data[SC_DANCING].timer!=-1 ){ // ‰‰‘t/ƒ_ƒ“ƒXŽg—p’† + sd->speed = (short) ((double)sd->speed * (6.- 0.4 * pc_checkskill(sd, ((s_class.job == 19) ? BA_MUSICALLESSON : DC_DANCINGLESSON)))); + //sd->speed*=4; + sd->nhealsp = 0; + sd->nshealsp = 0; + sd->nsshealsp = 0; + } + if(sd->sc_data[SC_CURSE].timer!=-1) + sd->speed += 450; + + if(sd->sc_data[SC_TRUESIGHT].timer!=-1) //ƒgƒDƒ‹?ƒTƒCƒg + sd->critical += sd->critical*(sd->sc_data[SC_TRUESIGHT].val1)/100; + +/* if(sd->sc_data[SC_VOLCANO].timer!=-1) // ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“(?«‚Íbattle.c‚Å) + sd->addeff[2]+=sd->sc_data[SC_VOLCANO].val2;//% of granting + if(sd->sc_data[SC_DELUGE].timer!=-1) // ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“(?«‚Íbattle.c‚Å) + sd->addeff[0]+=sd->sc_data[SC_DELUGE].val2;//% of granting + */ + if(sd->sc_data[SC_BERSERK].timer!=-1) { //All Def/MDef reduced to 0 while in Berserk [DracoRPG] + sd->def = sd->def2 = 0; + sd->mdef = sd->mdef2 = 0; + sd->flee -= sd->flee*50/100; + aspd_rate -= 30; + //sd->base_atk *= 3; + } + if(sd->sc_data[SC_KEEPING].timer!=-1) + sd->def = 100; + if(sd->sc_data[SC_BARRIER].timer!=-1) + sd->mdef = 100; + + if(sd->sc_data[SC_JOINTBEAT].timer!=-1) { // Random break [DracoRPG] + switch(sd->sc_data[SC_JOINTBEAT].val2) { + case 1: //Ankle break + sd->speed_rate += 50; + break; + case 2: //Wrist break + sd->aspd_rate += 25; + break; + case 3: //Knee break + sd->speed_rate += 30; + sd->aspd_rate += 10; + break; + case 4: //Shoulder break + sd->def2 -= sd->def2*50/100; + break; + case 5: //Waist break + sd->def2 -= sd->def2*50/100; + sd->base_atk -= sd->base_atk*25/100; + break; + } + } + + if(sd->sc_data[SC_GOSPEL].timer!=-1) { + if (sd->sc_data[SC_GOSPEL].val4 == BCT_PARTY){ + switch (sd->sc_data[SC_GOSPEL].val3) + { + case 4: + sd->status.max_hp += sd->status.max_hp * 25 / 100; + if(sd->status.max_hp > battle_config.max_hp) + sd->status.max_hp = battle_config.max_hp; + break; + case 5: + sd->status.max_sp += sd->status.max_sp * 25 / 100; + if(sd->status.max_sp > battle_config.max_sp) + sd->status.max_sp = battle_config.max_sp; + break; + case 11: + sd->def += sd->def * 25 / 100; + sd->def2 += sd->def2 * 25 / 100; + break; + case 12: + sd->base_atk += sd->base_atk * 8 / 100; + break; + case 13: + sd->flee += sd->flee * 5 / 100; + break; + case 14: + sd->hit += sd->hit * 5 / 100; + break; + } + } else if (sd->sc_data[SC_GOSPEL].val4 == BCT_ENEMY){ + switch (sd->sc_data[SC_GOSPEL].val3) + { + case 5: + sd->def = 0; + sd->def2 = 0; + break; + case 6: + sd->base_atk = 0; + sd->watk = 0; + sd->watk2 = 0; + break; + case 7: + sd->flee = 0; + break; + case 8: + sd->speed_rate += 75; + aspd_rate += 75; + break; + } + } + } + // custom stats, since there's no info on how much it actually gives ^^; [Celest] + if (sd->sc_data[SC_GUILDAURA].timer != -1) { + if (sd->sc_data[SC_GUILDAURA].val4 & 1<<4) { + sd->hit += 10; + sd->flee += 10; + } + } + } + + if (sd->speed_rate <= 0) + sd->speed_rate = 1; + + if(sd->speed_rate != 100) + sd->speed = sd->speed*sd->speed_rate/100; + if(sd->speed < 1) sd->speed = 1; + if(aspd_rate != 100) + sd->aspd = sd->aspd*aspd_rate/100; + if(pc_isriding(sd)) // ‹R•ºC—û + sd->aspd = sd->aspd*(100 + 10*(5 - pc_checkskill(sd,KN_CAVALIERMASTERY)))/ 100; + if(sd->aspd < battle_config.max_aspd) sd->aspd = battle_config.max_aspd; + sd->amotion = sd->aspd; + sd->dmotion = 800-sd->paramc[1]*4; + if(sd->dmotion<400) + sd->dmotion = 400; + if(sd->skilltimer != -1 && (skill = pc_checkskill(sd,SA_FREECAST)) > 0) { + sd->prev_speed = sd->speed; + sd->speed = sd->speed*(175 - skill*5)/100; + } + + if(sd->status.hp>sd->status.max_hp) + sd->status.hp=sd->status.max_hp; + if(sd->status.sp>sd->status.max_sp) + sd->status.sp=sd->status.max_sp; + + if(first&4) + return 0; + if(first&3) { + clif_updatestatus(sd,SP_SPEED); + clif_updatestatus(sd,SP_MAXHP); + clif_updatestatus(sd,SP_MAXSP); + if(first&1) { + clif_updatestatus(sd,SP_HP); + clif_updatestatus(sd,SP_SP); + } + return 0; + } + + if(b_class != sd->view_class) { + clif_changelook(&sd->bl,LOOK_BASE,sd->view_class); +#if PACKETVER < 4 + clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); + clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); +#else + clif_changelook(&sd->bl,LOOK_WEAPON,0); +#endif + } + + if( memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill)) || b_attackrange != sd->attackrange) + clif_skillinfoblock(sd); // ƒXƒLƒ‹‘—M + + if(b_speed != sd->speed) + clif_updatestatus(sd,SP_SPEED); + if(b_weight != sd->weight) + clif_updatestatus(sd,SP_WEIGHT); + if(b_max_weight != sd->max_weight) { + clif_updatestatus(sd,SP_MAXWEIGHT); + pc_checkweighticon(sd); + } + for(i=0;i<6;i++) + if(b_paramb[i] + b_parame[i] != sd->paramb[i] + sd->parame[i]) + clif_updatestatus(sd,SP_STR+i); + if(b_hit != sd->hit) + clif_updatestatus(sd,SP_HIT); + if(b_flee != sd->flee) + clif_updatestatus(sd,SP_FLEE1); + if(b_aspd != sd->aspd) + clif_updatestatus(sd,SP_ASPD); + if(b_watk != sd->watk || b_base_atk != sd->base_atk) + clif_updatestatus(sd,SP_ATK1); + if(b_def != sd->def) + clif_updatestatus(sd,SP_DEF1); + if(b_watk2 != sd->watk2) + clif_updatestatus(sd,SP_ATK2); + if(b_def2 != sd->def2) + clif_updatestatus(sd,SP_DEF2); + if(b_flee2 != sd->flee2) + clif_updatestatus(sd,SP_FLEE2); + if(b_critical != sd->critical) + clif_updatestatus(sd,SP_CRITICAL); + if(b_matk1 != sd->matk1) + clif_updatestatus(sd,SP_MATK1); + if(b_matk2 != sd->matk2) + clif_updatestatus(sd,SP_MATK2); + if(b_mdef != sd->mdef) + clif_updatestatus(sd,SP_MDEF1); + if(b_mdef2 != sd->mdef2) + clif_updatestatus(sd,SP_MDEF2); + if(b_attackrange != sd->attackrange) + clif_updatestatus(sd,SP_ATTACKRANGE); + if(b_max_hp != sd->status.max_hp) + clif_updatestatus(sd,SP_MAXHP); + if(b_max_sp != sd->status.max_sp) + clif_updatestatus(sd,SP_MAXSP); + if(b_hp != sd->status.hp) + clif_updatestatus(sd,SP_HP); + if(b_sp != sd->status.sp) + clif_updatestatus(sd,SP_SP); + +/* if(before.cart_num != before.cart_num || before.cart_max_num != before.cart_max_num || + before.cart_weight != before.cart_weight || before.cart_max_weight != before.cart_max_weight ) + clif_updatestatus(sd,SP_CARTINFO);*/ + + //if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 && + if(sd->status.hp<sd->status.max_hp>>2 && sd->sc_data[SC_AUTOBERSERK].timer != -1 && + (sd->sc_data[SC_PROVOKE].timer==-1 || sd->sc_data[SC_PROVOKE].val2==0 ) && !pc_isdead(sd)) + // ƒI?ƒgƒo?ƒT?ƒN?“® + status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0); + + return 0; +} + +/*========================================== + * For quick calculating [Celest] + *------------------------------------------ + */ +int status_calc_speed (struct map_session_data *sd) +{ + int b_speed, skill; + struct pc_base_job s_class; + + nullpo_retr(0, sd); + + s_class = pc_calc_base_job(sd->status.class_); + + b_speed = sd->speed; + sd->speed = DEFAULT_WALK_SPEED ; + + if(sd->sc_count){ + if(sd->sc_data[SC_INCREASEAGI].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1){ // ‘¬“x?‰Á + sd->speed -= sd->speed *25/100; + } + if(sd->sc_data[SC_DECREASEAGI].timer!=-1) { + sd->speed = sd->speed *125/100; + } + if(sd->sc_data[SC_CLOAKING].timer!=-1) { + sd->speed = sd->speed * (sd->sc_data[SC_CLOAKING].val3-sd->sc_data[SC_CLOAKING].val1*3) /100; + } + if(sd->sc_data[SC_CHASEWALK].timer!=-1) { + sd->speed = sd->speed * sd->sc_data[SC_CHASEWALK].val3 /100; + } + if(sd->sc_data[SC_QUAGMIRE].timer!=-1){ + sd->speed = sd->speed*3/2; + } + if(sd->sc_data[SC_WINDWALK].timer!=-1 && sd->sc_data[SC_INCREASEAGI].timer==-1) { + sd->speed -= sd->speed *(sd->sc_data[SC_WINDWALK].val1*2)/100; + } + if(sd->sc_data[SC_CARTBOOST].timer!=-1) { + sd->speed -= (DEFAULT_WALK_SPEED * 20)/100; + } + if(sd->sc_data[SC_BERSERK].timer!=-1) { + sd->speed -= sd->speed *25/100; + } + if(sd->sc_data[SC_WEDDING].timer!=-1) { + sd->speed = 2*DEFAULT_WALK_SPEED; + } + if(sd->sc_data[SC_DONTFORGETME].timer!=-1){ + sd->speed= sd->speed*(100+sd->sc_data[SC_DONTFORGETME].val1*2 + sd->sc_data[SC_DONTFORGETME].val2 + (sd->sc_data[SC_DONTFORGETME].val3&0xffff))/100; + } + if(sd->sc_data[SC_STEELBODY].timer!=-1){ + sd->speed = (sd->speed * 125) / 100; + } + if(sd->sc_data[SC_DEFENDER].timer != -1) { + sd->speed = (sd->speed * (155 - sd->sc_data[SC_DEFENDER].val1*5)) / 100; + } + if( sd->sc_data[SC_DANCING].timer!=-1 ){ + sd->speed = (int) ((double)sd->speed * (6.- 0.4 * pc_checkskill(sd, ((s_class.job == 19) ? BA_MUSICALLESSON : DC_DANCINGLESSON)))); + } + if(sd->sc_data[SC_CURSE].timer!=-1) + sd->speed += 450; + if(sd->sc_data[SC_SLOWDOWN].timer!=-1) + sd->speed = sd->speed*150/100; + if(sd->sc_data[SC_SPEEDUP0].timer!=-1) + sd->speed -= sd->speed*25/100; + } + + if(sd->status.option&2 && (skill = pc_checkskill(sd,RG_TUNNELDRIVE))>0 ) + sd->speed += (100-16*skill)*DEFAULT_WALK_SPEED/100; + if (pc_iscarton(sd) && (skill=pc_checkskill(sd,MC_PUSHCART))>0) + sd->speed += (short) ((10-skill) * (DEFAULT_WALK_SPEED * 0.1)); + else if (pc_isriding(sd)) { + sd->speed -= (short) ((0.25 * DEFAULT_WALK_SPEED)); + } + if((skill=pc_checkskill(sd,TF_MISS))>0) + if(s_class.job==12) + sd->speed -= (short) (sd->speed *(skill*1.5)/100); + + if(sd->speed_rate != 100) + sd->speed = sd->speed*sd->speed_rate/100; + if(sd->speed < 1) sd->speed = 1; + + if(sd->skilltimer != -1 && (skill = pc_checkskill(sd,SA_FREECAST)) > 0) { + sd->prev_speed = sd->speed; + sd->speed = sd->speed*(175 - skill*5)/100; + } + + if(b_speed != sd->speed) + clif_updatestatus(sd,SP_SPEED); + + return 0; +} + +/*========================================== + * ‘ÎÛ‚ÌClass‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_class(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return ((struct mob_data *)bl)->class_; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->status.class_; + else if(bl->type==BL_PET && (struct pet_data *)bl) + return ((struct pet_data *)bl)->class_; + else + return 0; +} +/*========================================== + * ‘ÎÛ‚Ì•ûŒü‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_dir(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return ((struct mob_data *)bl)->dir; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->dir; + else if(bl->type==BL_PET && (struct pet_data *)bl) + return ((struct pet_data *)bl)->dir; + else + return 0; +} +/*========================================== + * ‘Îۂ̃Œƒxƒ‹‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_lv(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return ((struct mob_data *)bl)->level; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->status.base_level; + else if(bl->type==BL_PET && (struct pet_data *)bl) + return ((struct pet_data *)bl)->msd->pet.level; + else + return 0; +} + +/*========================================== + * ‘ÎÛ‚ÌŽË’ö‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_range(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return mob_db[((struct mob_data *)bl)->class_].range; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->attackrange; + else if(bl->type==BL_PET && (struct pet_data *)bl) + return mob_db[((struct pet_data *)bl)->class_].range; + else + return 0; +} +/*========================================== + * ‘ÎÛ‚ÌHP‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_hp(struct block_list *bl) +{ + nullpo_retr(1, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return ((struct mob_data *)bl)->hp; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->status.hp; + else + return 1; +} +/*========================================== + * ‘ÎÛ‚ÌMHP‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_max_hp(struct block_list *bl) +{ + nullpo_retr(1, bl); + + if(bl->type==BL_PC && ((struct map_session_data *)bl)) + return ((struct map_session_data *)bl)->status.max_hp; + else { + struct status_change *sc_data; + int max_hp = 1; + + if(bl->type == BL_MOB) { + struct mob_data *md; + nullpo_retr(1, md = (struct mob_data *)bl); + max_hp = mob_db[md->class_].max_hp; + + if(battle_config.mobs_level_up) // mobs leveling up increase [Valaris] + max_hp += (md->level - mob_db[md->class_].lv) * status_get_vit(bl); + + if(mob_db[md->class_].mexp > 0) { //MVP Monsters + if(battle_config.mvp_hp_rate != 100) { + double hp = (double)max_hp * battle_config.mvp_hp_rate / 100.0; + max_hp = (hp > 0x7FFFFFFF ? 0x7FFFFFFF : (int)hp); + } + } + else { //Common MONSTERS + if(battle_config.monster_hp_rate != 100) { + double hp = (double)max_hp * battle_config.monster_hp_rate / 100.0; + max_hp = (hp > 0x7FFFFFFF ? 0x7FFFFFFF : (int)hp); + } + } + } + else if(bl->type == BL_PET) { + struct pet_data *pd; + nullpo_retr(1, pd = (struct pet_data*)bl); + max_hp = mob_db[pd->class_].max_hp; + + if(mob_db[pd->class_].mexp > 0) { //MVP Monsters + if(battle_config.mvp_hp_rate != 100) + max_hp = (max_hp * battle_config.mvp_hp_rate)/100; + } + else { //Common MONSTERS + if(battle_config.monster_hp_rate != 100) + max_hp = (max_hp * battle_config.monster_hp_rate)/100; + } + } + + sc_data = status_get_sc_data(bl); + if(sc_data) { + if(sc_data[SC_APPLEIDUN].timer != -1) + max_hp += ((5 + sc_data[SC_APPLEIDUN].val1 * 2 + ((sc_data[SC_APPLEIDUN].val2 + 1) >> 1) + + sc_data[SC_APPLEIDUN].val3 / 10) * max_hp)/100; + if(sc_data[SC_GOSPEL].timer != -1 && + sc_data[SC_GOSPEL].val4 == BCT_PARTY && + sc_data[SC_GOSPEL].val3 == 4) + max_hp += max_hp * 25 / 100; + } + if(max_hp < 1) max_hp = 1; + return max_hp; + } + return 1; +} +/*========================================== + * ‘ÎÛ‚ÌStr‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_str(struct block_list *bl) +{ + int str = 0; + nullpo_retr(0, bl); + + if (bl->type == BL_PC && ((struct map_session_data *)bl)) + return ((struct map_session_data *)bl)->paramc[0]; + else { + struct status_change *sc_data; + sc_data = status_get_sc_data(bl); + + if(bl->type == BL_MOB && ((struct mob_data *)bl)) { + str = mob_db[((struct mob_data *)bl)->class_].str; + if(battle_config.mobs_level_up) // mobs leveling up increase [Valaris] + str += ((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv; + } + else if(bl->type == BL_PET && ((struct pet_data *)bl)) + str = mob_db[((struct pet_data *)bl)->class_].str; + + if(sc_data) { + if(sc_data[SC_LOUD].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1) + str += 4; + if( sc_data[SC_BLESSING].timer != -1){ // ƒuƒŒƒbƒVƒ“ƒO + int race = status_get_race(bl); + if(battle_check_undead(race,status_get_elem_type(bl)) || race == 6) + str >>= 1; // ˆ« –‚/•sŽ€ + else str += sc_data[SC_BLESSING].val1; // ‚»‚Ì‘¼ + } + if(sc_data[SC_TRUESIGHT].timer!=-1) // ƒgƒDƒ‹[ƒTƒCƒg + str += 5; + } + } + if(str < 0) str = 0; + return str; +} +/*========================================== + * ‘ÎÛ‚ÌAgi‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ + +int status_get_agi(struct block_list *bl) +{ + int agi=0; + nullpo_retr(0, bl); + + if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->paramc[1]; + else { + struct status_change *sc_data; + sc_data = status_get_sc_data(bl); + if(bl->type == BL_MOB && (struct mob_data *)bl) { + agi = mob_db[((struct mob_data *)bl)->class_].agi; + if(battle_config.mobs_level_up) // increase of mobs leveling up [Valaris] + agi += ((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv; + } + else if(bl->type == BL_PET && (struct pet_data *)bl) + agi = mob_db[((struct pet_data *)bl)->class_].agi; + + if(sc_data) { + if(sc_data[SC_INCREASEAGI].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // ‘¬“x‘‰Á(PC‚Ípc.c‚Å) + agi += 2 + sc_data[SC_INCREASEAGI].val1; + if(sc_data[SC_CONCENTRATE].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1) + agi += agi * (2 + sc_data[SC_CONCENTRATE].val1)/100; + if(sc_data[SC_DECREASEAGI].timer!=-1) // ‘¬“xŒ¸ + agi -= 2 + sc_data[SC_DECREASEAGI].val1; + if(sc_data[SC_QUAGMIRE].timer!=-1 ) { // ƒNƒ@ƒOƒ}ƒCƒA + //agi >>= 1; + //int agib = agi*(sc_data[SC_QUAGMIRE].val1*10)/100; + //agi -= agib > 50 ? 50 : agib; + agi -= sc_data[SC_QUAGMIRE].val1*10; + } + if(sc_data[SC_TRUESIGHT].timer!=-1) // ƒgƒDƒ‹[ƒTƒCƒg + agi += 5; + } + } + if(agi < 0) agi = 0; + return agi; +} +/*========================================== + * ‘ÎÛ‚ÌVit‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_vit(struct block_list *bl) +{ + int vit = 0; + nullpo_retr(0, bl); + + if(bl->type == BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->paramc[2]; + else { + struct status_change *sc_data; + sc_data = status_get_sc_data(bl); + if(bl->type == BL_MOB && (struct mob_data *)bl) { + vit = mob_db[((struct mob_data *)bl)->class_].vit; + if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris] + vit += ((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv; + } + else if(bl->type == BL_PET && (struct pet_data *)bl) + vit = mob_db[((struct pet_data *)bl)->class_].vit; + if(sc_data) { + if(sc_data[SC_STRIPARMOR].timer != -1) + vit = vit*60/100; + if(sc_data[SC_TRUESIGHT].timer!=-1) // ƒgƒDƒ‹[ƒTƒCƒg + vit += 5; + } + } + if(vit < 0) vit = 0; + return vit; +} +/*========================================== + * ‘ÎÛ‚ÌInt‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_int(struct block_list *bl) +{ + int int_=0; + nullpo_retr(0, bl); + + if(bl->type == BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->paramc[3]; + else { + struct status_change *sc_data; + sc_data = status_get_sc_data(bl); + if(bl->type == BL_MOB && (struct mob_data *)bl){ + int_ = mob_db[((struct mob_data *)bl)->class_].int_; + if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris] + int_ += ((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv; + } + else if(bl->type == BL_PET && (struct pet_data *)bl) + int_ = mob_db[((struct pet_data *)bl)->class_].int_; + + if(sc_data) { + if(sc_data[SC_BLESSING].timer != -1){ // ƒuƒŒƒbƒVƒ“ƒO + int race = status_get_race(bl); + if(battle_check_undead(race,status_get_elem_type(bl)) || race == 6 ) + int_ >>= 1; // ˆ« –‚/•sŽ€ + else + int_ += sc_data[SC_BLESSING].val1; // ‚»‚Ì‘¼ + } + if(sc_data[SC_STRIPHELM].timer != -1) + int_ = int_*60/100; + if(sc_data[SC_TRUESIGHT].timer!=-1) // ƒgƒDƒ‹[ƒTƒCƒg + int_ += 5; + } + } + if(int_ < 0) int_ = 0; + return int_; +} +/*========================================== + * ‘ÎÛ‚ÌDex‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_dex(struct block_list *bl) +{ + int dex = 0; + nullpo_retr(0, bl); + + if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->paramc[4]; + else { + struct status_change *sc_data; + sc_data = status_get_sc_data(bl); + if(bl->type == BL_MOB && (struct mob_data *)bl) { + dex = mob_db[((struct mob_data *)bl)->class_].dex; + if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris] + dex += ((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv; + } + else if(bl->type == BL_PET && (struct pet_data *)bl) + dex = mob_db[((struct pet_data *)bl)->class_].dex; + + if(sc_data) { + if(sc_data[SC_CONCENTRATE].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1) + dex += dex*(2+sc_data[SC_CONCENTRATE].val1)/100; + if(sc_data[SC_BLESSING].timer != -1){ // ƒuƒŒƒbƒVƒ“ƒO + int race = status_get_race(bl); + if(battle_check_undead(race,status_get_elem_type(bl)) || race == 6 ) + dex >>= 1; // ˆ« –‚/•sŽ€ + else dex += sc_data[SC_BLESSING].val1; // ‚»‚Ì‘¼ + } + if(sc_data[SC_QUAGMIRE].timer!=-1) { // ƒNƒ@ƒOƒ}ƒCƒA + // dex >>= 1; + //int dexb = dex*(sc_data[SC_QUAGMIRE].val1*10)/100; + //dex -= dexb > 50 ? 50 : dexb; + dex -= sc_data[SC_QUAGMIRE].val1*10; + } + if(sc_data[SC_TRUESIGHT].timer!=-1) // ƒgƒDƒ‹[ƒTƒCƒg + dex += 5; + } + } + if(dex < 0) dex = 0; + return dex; +} +/*========================================== + * ‘ÎÛ‚ÌLuk‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_luk(struct block_list *bl) +{ + int luk = 0; + nullpo_retr(0, bl); + + if(bl->type == BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->paramc[5]; + else { + struct status_change *sc_data; + sc_data = status_get_sc_data(bl); + if(bl->type == BL_MOB && (struct mob_data *)bl) { + luk = mob_db[((struct mob_data *)bl)->class_].luk; + if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris] + luk += ((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv; + } + else if(bl->type == BL_PET && (struct pet_data *)bl) + luk = mob_db[((struct pet_data *)bl)->class_].luk; + if(sc_data) { + if(sc_data[SC_GLORIA].timer!=-1) // ƒOƒƒŠƒA(PC‚Ípc.c‚Å) + luk += 30; + if(sc_data[SC_TRUESIGHT].timer!=-1) // ƒgƒDƒ‹[ƒTƒCƒg + luk += 5; + if(sc_data[SC_CURSE].timer!=-1) // Žô‚¢ + luk = 0; + } + } + if(luk < 0) luk = 0; + return luk; +} + +/*========================================== + * ‘ÎÛ‚ÌFlee‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å1ˆÈã + *------------------------------------------ + */ +int status_get_flee(struct block_list *bl) +{ + int flee = 1; + nullpo_retr(1, bl); + + if(bl->type == BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->flee; + else { + struct status_change *sc_data; + sc_data = status_get_sc_data(bl); + flee = status_get_agi(bl) + status_get_lv(bl); + + if(sc_data){ + if(sc_data[SC_WHISTLE].timer!=-1) + flee += flee*(sc_data[SC_WHISTLE].val1+sc_data[SC_WHISTLE].val2 + +(sc_data[SC_WHISTLE].val3>>16))/100; + if(sc_data[SC_BLIND].timer!=-1) + flee -= flee*25/100; + if(sc_data[SC_WINDWALK].timer!=-1) // ƒEƒBƒ“ƒhƒEƒH[ƒN + flee += flee*(sc_data[SC_WINDWALK].val2)/100; + if(sc_data[SC_SPIDERWEB].timer!=-1) //ƒXƒpƒCƒ_[ƒEƒFƒu + flee -= flee*50/100; + if(sc_data[SC_GOSPEL].timer!=-1) { + if (sc_data[SC_GOSPEL].val4 == BCT_PARTY && + sc_data[SC_GOSPEL].val3 == 13) + flee += flee*5/100; + else if (sc_data[SC_GOSPEL].val4 == BCT_ENEMY && + sc_data[SC_GOSPEL].val3 == 7) + flee = 0; + } + } + } + if(flee < 1) flee = 1; + return flee; +} +/*========================================== + * ‘ÎÛ‚ÌHit‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å1ˆÈã + *------------------------------------------ + */ +int status_get_hit(struct block_list *bl) +{ + int hit = 1; + nullpo_retr(1, bl); + if(bl->type == BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->hit; + else { + struct status_change *sc_data; + sc_data = status_get_sc_data(bl); + hit = status_get_dex(bl) + status_get_lv(bl); + + if(sc_data) { + if(sc_data[SC_HUMMING].timer!=-1) // + hit += hit*(sc_data[SC_HUMMING].val1*2+sc_data[SC_HUMMING].val2 + +sc_data[SC_HUMMING].val3)/100; + if(sc_data[SC_BLIND].timer!=-1) // Žô‚¢ + hit -= hit*25/100; + if(sc_data[SC_TRUESIGHT].timer!=-1) // ƒgƒDƒ‹[ƒTƒCƒg + hit += 3*(sc_data[SC_TRUESIGHT].val1); + if(sc_data[SC_CONCENTRATION].timer!=-1) //ƒRƒ“ƒZƒ“ƒgƒŒ[ƒVƒ‡ƒ“ + hit += (hit*(10*(sc_data[SC_CONCENTRATION].val1)))/100; + if(sc_data[SC_GOSPEL].timer!=-1 && + sc_data[SC_GOSPEL].val4 == BCT_PARTY && + sc_data[SC_GOSPEL].val3 == 14) + hit += hit*5/100; + if(sc_data[SC_EXPLOSIONSPIRITS].timer!=-1) + hit += 20*sc_data[SC_EXPLOSIONSPIRITS].val1; + } + } + if(hit < 1) hit = 1; + return hit; +} +/*========================================== + * ‘ÎÛ‚ÌŠ®‘S‰ñ”ð‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å1ˆÈã + *------------------------------------------ + */ +int status_get_flee2(struct block_list *bl) +{ + int flee2 = 1; + nullpo_retr(1, bl); + + if(bl->type==BL_PC && (struct map_session_data *)bl){ + return ((struct map_session_data *)bl)->flee2; + } else { + struct status_change *sc_data; + sc_data = status_get_sc_data(bl); + flee2 = status_get_luk(bl)+1; + + if(sc_data) { + if(sc_data[SC_WHISTLE].timer!=-1) + flee2 += (sc_data[SC_WHISTLE].val1+sc_data[SC_WHISTLE].val2 + +(sc_data[SC_WHISTLE].val3&0xffff))*10; + } + } + if(flee2 < 1) flee2 = 1; + return flee2; +} +/*========================================== + * ‘Îۂ̃NƒŠƒeƒBƒJƒ‹‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å1ˆÈã + *------------------------------------------ + */ +int status_get_critical(struct block_list *bl) +{ + int critical = 1; + nullpo_retr(1, bl); + + if(bl->type == BL_PC && (struct map_session_data *)bl){ + return ((struct map_session_data *)bl)->critical; + } else { + struct status_change *sc_data; + sc_data = status_get_sc_data(bl); + critical = status_get_luk(bl)*3 + 1; + + if(sc_data) { + if(sc_data[SC_FORTUNE].timer!=-1) + critical += (10+sc_data[SC_FORTUNE].val1+sc_data[SC_FORTUNE].val2 + + sc_data[SC_FORTUNE].val3)*10; + if(sc_data[SC_EXPLOSIONSPIRITS].timer!=-1) + critical += sc_data[SC_EXPLOSIONSPIRITS].val2; + if(sc_data[SC_TRUESIGHT].timer!=-1) //ƒgƒDƒ‹[ƒTƒCƒg + critical += critical*sc_data[SC_TRUESIGHT].val1/100; + } + } + if(critical < 1) critical = 1; + return critical; +} +/*========================================== + * base_atk‚̎擾 + * –ß‚è‚Í®”‚Å1ˆÈã + *------------------------------------------ + */ +int status_get_baseatk(struct block_list *bl) +{ + int batk = 1; + nullpo_retr(1, bl); + + if(bl->type==BL_PC && (struct map_session_data *)bl) { + batk = ((struct map_session_data *)bl)->base_atk; //ݒ肳‚ê‚Ä‚¢‚ébase_atk + if (((struct map_session_data *)bl)->status.weapon < 16) + batk += ((struct map_session_data *)bl)->weapon_atk[((struct map_session_data *)bl)->status.weapon]; + } else { //‚»‚êˆÈŠO‚È‚ç + struct status_change *sc_data; + int str,dstr; + str = status_get_str(bl); //STR + dstr = str/10; + batk = dstr*dstr + str; //base_atk‚ðŒvŽZ‚·‚é + sc_data = status_get_sc_data(bl); + + if(sc_data) { //ó‘ÔˆÙí‚ ‚è + if(sc_data[SC_PROVOKE].timer!=-1) //PC‚Ńvƒƒ{ƒbƒN(SM_PROVOKE)ó‘Ô + batk = batk*(100+2*sc_data[SC_PROVOKE].val1)/100; //base_atk‘‰Á + if(sc_data[SC_CURSE].timer!=-1) //Žô‚í‚ê‚Ä‚¢‚½‚ç + batk -= batk*25/100; //base_atk‚ª25%Œ¸ + if(sc_data[SC_CONCENTRATION].timer!=-1) //ƒRƒ“ƒZƒ“ƒgƒŒ[ƒVƒ‡ƒ“ + batk += batk*(5*sc_data[SC_CONCENTRATION].val1)/100; + } + } + if(batk < 1) batk = 1; //base_atk‚ÍÅ’á‚Å‚à1 + return batk; +} +/*========================================== + * ‘ÎÛ‚ÌAtk‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_atk(struct block_list *bl) +{ + int atk = 0; + nullpo_retr(0, bl); + + if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data*)bl)->watk; + else { + struct status_change *sc_data; + sc_data=status_get_sc_data(bl); + + if(bl->type == BL_MOB && (struct mob_data *)bl) + atk = mob_db[((struct mob_data*)bl)->class_].atk1; + else if(bl->type == BL_PET && (struct pet_data *)bl) + atk = mob_db[((struct pet_data*)bl)->class_].atk1; + + if(sc_data) { + if(sc_data[SC_PROVOKE].timer!=-1) + atk = atk*(100+2*sc_data[SC_PROVOKE].val1)/100; + if(sc_data[SC_CURSE].timer!=-1) + atk -= atk*25/100; + if(sc_data[SC_CONCENTRATION].timer!=-1) //ƒRƒ“ƒZƒ“ƒgƒŒ[ƒVƒ‡ƒ“ + atk += atk*(5*sc_data[SC_CONCENTRATION].val1)/100; + if(sc_data[SC_EXPLOSIONSPIRITS].timer!=-1) + atk += (1000*sc_data[SC_EXPLOSIONSPIRITS].val1); + if(sc_data[SC_STRIPWEAPON].timer!=-1) + atk -= atk*10/100; + + if(sc_data[SC_GOSPEL].timer!=-1) { + if (sc_data[SC_GOSPEL].val4 == BCT_PARTY && + sc_data[SC_GOSPEL].val3 == 12) + atk += atk*8/100; + else if (sc_data[SC_GOSPEL].val4 == BCT_ENEMY && + sc_data[SC_GOSPEL].val3 == 6) + atk = 0; + } + } + } + if(atk < 0) atk = 0; + return atk; +} +/*========================================== + * ‘Îۂ̶ŽèAtk‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_atk_(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_PC && (struct map_session_data *)bl){ + int atk=((struct map_session_data*)bl)->watk_; + return atk; + } + else + return 0; +} +/*========================================== + * ‘ÎÛ‚ÌAtk2‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_atk2(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data*)bl)->watk2; + else { + struct status_change *sc_data=status_get_sc_data(bl); + int atk2=0; + if(bl->type==BL_MOB && (struct mob_data *)bl) + atk2 = mob_db[((struct mob_data*)bl)->class_].atk2; + else if(bl->type==BL_PET && (struct pet_data *)bl) + atk2 = mob_db[((struct pet_data*)bl)->class_].atk2; + if(sc_data) { + if( sc_data[SC_IMPOSITIO].timer!=-1) + atk2 += sc_data[SC_IMPOSITIO].val1*5; + if( sc_data[SC_PROVOKE].timer!=-1 ) + atk2 = atk2*(100+2*sc_data[SC_PROVOKE].val1)/100; + if( sc_data[SC_CURSE].timer!=-1 ) + atk2 -= atk2*25/100; + if(sc_data[SC_DRUMBATTLE].timer!=-1) + atk2 += sc_data[SC_DRUMBATTLE].val2; + if(sc_data[SC_NIBELUNGEN].timer!=-1 && (status_get_element(bl)/10) >= 8 ) + atk2 += sc_data[SC_NIBELUNGEN].val3; + if(sc_data[SC_STRIPWEAPON].timer!=-1) + atk2 = atk2*sc_data[SC_STRIPWEAPON].val2/100; + if(sc_data[SC_CONCENTRATION].timer!=-1) //ƒRƒ“ƒZƒ“ƒgƒŒ[ƒVƒ‡ƒ“ + atk2 += atk2*(5*sc_data[SC_CONCENTRATION].val1)/100; + if(sc_data[SC_EXPLOSIONSPIRITS].timer!=-1) + atk2 += (1000*sc_data[SC_EXPLOSIONSPIRITS].val1); + } + if(atk2 < 0) atk2 = 0; + return atk2; + } + return 0; +} +/*========================================== + * ‘Îۂ̶ŽèAtk2‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_atk_2(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data*)bl)->watk_2; + else + return 0; +} +/*========================================== + * ‘ÎÛ‚ÌMAtk1‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_matk1(struct block_list *bl) +{ + int matk = 0; + nullpo_retr(0, bl); + + if(bl->type == BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->matk1; + else { + struct status_change *sc_data; + int int_ = status_get_int(bl); + matk = int_+(int_/5)*(int_/5); + + sc_data = status_get_sc_data(bl); + if(sc_data) { + if(sc_data[SC_MINDBREAKER].timer!=-1) + matk = matk*(100+2*sc_data[SC_MINDBREAKER].val1)/100; + } + } + return matk; +} +/*========================================== + * ‘ÎÛ‚ÌMAtk2‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_matk2(struct block_list *bl) +{ + int matk = 0; + nullpo_retr(0, bl); + + if(bl->type == BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->matk2; + else { + struct status_change *sc_data = status_get_sc_data(bl); + int int_ = status_get_int(bl); + matk = int_+(int_/7)*(int_/7); + + if(sc_data) { + if(sc_data[SC_MINDBREAKER].timer!=-1) + matk = matk*(100+2*sc_data[SC_MINDBREAKER].val1)/100; + } + } + return matk; +} +/*========================================== + * ‘ÎÛ‚ÌDef‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_def(struct block_list *bl) +{ + struct status_change *sc_data; + int def=0,skilltimer=-1,skillid=0; + + nullpo_retr(0, bl); + sc_data=status_get_sc_data(bl); + if(bl->type==BL_PC && (struct map_session_data *)bl){ + def = ((struct map_session_data *)bl)->def; + skilltimer = ((struct map_session_data *)bl)->skilltimer; + skillid = ((struct map_session_data *)bl)->skillid; + } + else if(bl->type==BL_MOB && (struct mob_data *)bl) { + def = mob_db[((struct mob_data *)bl)->class_].def; + skilltimer = ((struct mob_data *)bl)->skilltimer; + skillid = ((struct mob_data *)bl)->skillid; + } + else if(bl->type==BL_PET && (struct pet_data *)bl) + def = mob_db[((struct pet_data *)bl)->class_].def; + + if(def < 1000000) { + if(sc_data) { + //“€Œ‹AΉ»Žž‚͉EƒVƒtƒg + if(sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)) + def >>= 1; + + if (bl->type != BL_PC) { + //ƒL[ƒsƒ“ƒOŽž‚ÍDEF100 + if( sc_data[SC_KEEPING].timer!=-1) + def = 100; + //ƒvƒƒ{ƒbƒNŽž‚ÍŒ¸ŽZ + if( sc_data[SC_PROVOKE].timer!=-1) + def = (def*(100 - 6*sc_data[SC_PROVOKE].val1)+50)/100; + //푾ŒÛ‚Ì‹¿‚«Žž‚͉ÁŽZ + if( sc_data[SC_DRUMBATTLE].timer!=-1) + def += sc_data[SC_DRUMBATTLE].val3; + //“łɂ©‚©‚Á‚Ä‚¢‚鎞‚ÍŒ¸ŽZ + if(sc_data[SC_POISON].timer!=-1) + def = def*75/100; + //ƒXƒgƒŠƒbƒvƒV[ƒ‹ƒhŽž‚ÍŒ¸ŽZ + if(sc_data[SC_STRIPSHIELD].timer!=-1) + def = def*sc_data[SC_STRIPSHIELD].val2/100; + //ƒVƒOƒiƒ€ƒNƒ‹ƒVƒXŽž‚ÍŒ¸ŽZ + if(sc_data[SC_SIGNUMCRUCIS].timer!=-1) + def = def * (100 - sc_data[SC_SIGNUMCRUCIS].val2)/100; + //‰i‰“‚̬“׎ž‚ÍDEF0‚ɂȂé + if(sc_data[SC_ETERNALCHAOS].timer!=-1) + def = 0; + //ƒRƒ“ƒZƒ“ƒgƒŒ[ƒVƒ‡ƒ“Žž‚ÍŒ¸ŽZ + if( sc_data[SC_CONCENTRATION].timer!=-1) + def = (def*(100 - 5*sc_data[SC_CONCENTRATION].val1))/100; + + if(sc_data[SC_GOSPEL].timer!=-1) { + if (sc_data[SC_GOSPEL].val4 == BCT_PARTY && + sc_data[SC_GOSPEL].val3 == 11) + def += def*25/100; + else if (sc_data[SC_GOSPEL].val4 == BCT_ENEMY && + sc_data[SC_GOSPEL].val3 == 5) + def = 0; + } + if(sc_data[SC_JOINTBEAT].timer!=-1) { + if (sc_data[SC_JOINTBEAT].val2 == 4) + def -= def*50/100; + else if (sc_data[SC_JOINTBEAT].val2 == 5) + def -= def*25/100; + } + } + } + //‰r¥’†‚͉r¥ŽžŒ¸ŽZ—¦‚ÉŠî‚¢‚ÄŒ¸ŽZ + if(skilltimer != -1) { + int def_rate = skill_get_castdef(skillid); + if(def_rate != 0) + def = (def * (100 - def_rate))/100; + } + } + if(def < 0) def = 0; + return def; +} +/*========================================== + * ‘ÎÛ‚ÌMDef‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_mdef(struct block_list *bl) +{ + struct status_change *sc_data; + int mdef=0; + + nullpo_retr(0, bl); + sc_data=status_get_sc_data(bl); + if(bl->type==BL_PC && (struct map_session_data *)bl) + mdef = ((struct map_session_data *)bl)->mdef; + else if(bl->type==BL_MOB && (struct mob_data *)bl) + mdef = mob_db[((struct mob_data *)bl)->class_].mdef; + else if(bl->type==BL_PET && (struct pet_data *)bl) + mdef = mob_db[((struct pet_data *)bl)->class_].mdef; + + if(mdef < 1000000) { + if(sc_data) { + //ƒoƒŠƒA[ó‘ÔŽž‚ÍMDEF100 + if(sc_data[SC_BARRIER].timer != -1) + mdef = 100; + //“€Œ‹AΉ»Žž‚Í1.25”{ + if(sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)) + mdef = mdef*125/100; + if( sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC) + mdef -= (mdef*6*sc_data[SC_MINDBREAKER].val1)/100; + } + } + if(mdef < 0) mdef = 0; + return mdef; +} +/*========================================== + * ‘ÎÛ‚ÌDef2‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å1ˆÈã + *------------------------------------------ + */ +int status_get_def2(struct block_list *bl) +{ + int def2 = 1; + nullpo_retr(1, bl); + + if(bl->type==BL_PC) + return ((struct map_session_data *)bl)->def2; + else { + struct status_change *sc_data; + + if(bl->type==BL_MOB) + def2 = mob_db[((struct mob_data *)bl)->class_].vit; + else if(bl->type==BL_PET) + def2 = mob_db[((struct pet_data *)bl)->class_].vit; + + sc_data = status_get_sc_data(bl); + if(sc_data) { + if(sc_data[SC_ANGELUS].timer != -1) + def2 = def2*(110+5*sc_data[SC_ANGELUS].val1)/100; + if(sc_data[SC_PROVOKE].timer!=-1) + def2 = (def2*(100 - 6*sc_data[SC_PROVOKE].val1)+50)/100; + if(sc_data[SC_POISON].timer!=-1) + def2 = def2*75/100; + //ƒRƒ“ƒZƒ“ƒgƒŒ[ƒVƒ‡ƒ“Žž‚ÍŒ¸ŽZ + if( sc_data[SC_CONCENTRATION].timer!=-1) + def2 = def2*(100 - 5*sc_data[SC_CONCENTRATION].val1)/100; + + if(sc_data[SC_GOSPEL].timer!=-1) { + if (sc_data[SC_GOSPEL].val4 == BCT_PARTY && + sc_data[SC_GOSPEL].val3 == 11) + def2 += def2*25/100; + else if (sc_data[SC_GOSPEL].val4 == BCT_ENEMY && + sc_data[SC_GOSPEL].val3 == 5) + def2 = 0; + } + } + } + if(def2 < 1) def2 = 1; + return def2; +} +/*========================================== + * ‘ÎÛ‚ÌMDef2‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å0ˆÈã + *------------------------------------------ + */ +int status_get_mdef2(struct block_list *bl) +{ + int mdef2 = 0; + nullpo_retr(0, bl); + + if(bl->type == BL_PC) + return ((struct map_session_data *)bl)->mdef2 + (((struct map_session_data *)bl)->paramc[2]>>1); + else { + struct status_change *sc_data = status_get_sc_data(bl); + if(bl->type == BL_MOB) + mdef2 = mob_db[((struct mob_data *)bl)->class_].int_ + (mob_db[((struct mob_data *)bl)->class_].vit>>1); + else if(bl->type == BL_PET) + mdef2 = mob_db[((struct pet_data *)bl)->class_].int_ + (mob_db[((struct pet_data *)bl)->class_].vit>>1); + if(sc_data) { + if(sc_data[SC_MINDBREAKER].timer!=-1) + mdef2 -= (mdef2*6*sc_data[SC_MINDBREAKER].val1)/100; + } + } + if(mdef2 < 0) mdef2 = 0; + return mdef2; +} +/*========================================== + * ‘ÎÛ‚ÌSpeed(ˆÚ“®‘¬“x)‚ð•Ô‚·(”Ä—p) + * –ß‚è‚Í®”‚Å1ˆÈã + * Speed‚ͬ‚³‚¢‚Ù‚¤‚ªˆÚ“®‘¬“x‚ª‘¬‚¢ + *------------------------------------------ + */ +int status_get_speed(struct block_list *bl) +{ + nullpo_retr(1000, bl); + if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->speed; + else { + struct status_change *sc_data=status_get_sc_data(bl); + int speed = 1000; + if(bl->type==BL_MOB && (struct mob_data *)bl) { + speed = ((struct mob_data *)bl)->speed; + if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris] + speed-=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv; + } + else if(bl->type==BL_PET && (struct pet_data *)bl) + speed = ((struct pet_data *)bl)->msd->petDB->speed; + + if(sc_data) { + //‘¬“x‘‰ÁŽž‚Í25%Œ¸ŽZ + if(sc_data[SC_INCREASEAGI].timer!=-1) + speed -= speed*25/100; + //ƒEƒBƒ“ƒhƒEƒH[ƒNŽž‚ÍLv*2%Œ¸ŽZ + else if(sc_data[SC_WINDWALK].timer!=-1) + speed -= (speed*(sc_data[SC_WINDWALK].val1*2))/100; + //‘¬“xŒ¸Žž‚Í25%‰ÁŽZ + if(sc_data[SC_DECREASEAGI].timer!=-1) + speed = speed*125/100; + //ƒNƒ@ƒOƒ}ƒCƒAŽž‚Í50%‰ÁŽZ + if(sc_data[SC_QUAGMIRE].timer!=-1) + speed = speed*3/2; + //Ž„‚ð–Y‚ê‚È‚¢‚ÅcŽž‚͉ÁŽZ + if(sc_data[SC_DONTFORGETME].timer!=-1) + speed = speed*(100+sc_data[SC_DONTFORGETME].val1*2 + sc_data[SC_DONTFORGETME].val2 + (sc_data[SC_DONTFORGETME].val3&0xffff))/100; + //‹à„Žž‚Í25%‰ÁŽZ + if(sc_data[SC_STEELBODY].timer!=-1) + speed = speed*125/100; + //ƒfƒBƒtƒFƒ“ƒ_[Žž‚͉ÁŽZ + if(sc_data[SC_DEFENDER].timer!=-1) + speed = (speed * (155 - sc_data[SC_DEFENDER].val1*5)) / 100; + //—x‚èó‘Ô‚Í4”{’x‚¢ + if(sc_data[SC_DANCING].timer!=-1 ) + speed *= 6; + //Žô‚¢Žž‚Í450‰ÁŽZ + if(sc_data[SC_CURSE].timer!=-1) + speed = speed + 450; + if(sc_data[SC_SLOWDOWN].timer!=-1) + speed = speed*150/100; + if(sc_data[SC_SPEEDUP0].timer!=-1) + speed -= speed*25/100; + if(sc_data[SC_GOSPEL].timer!=-1 && + sc_data[SC_GOSPEL].val4 == BCT_ENEMY && + sc_data[SC_GOSPEL].val3 == 8) + speed = speed*125/100; + if(sc_data[SC_JOINTBEAT].timer!=-1) { + if (sc_data[SC_JOINTBEAT].val2 == 1) + speed = speed*150/100; + else if (sc_data[SC_JOINTBEAT].val2 == 3) + speed = speed*130/100; + } + } + if(speed < 1) speed = 1; + return speed; + } + + return 1000; +} +/*========================================== + * ‘ÎÛ‚ÌaDelay(UŒ‚ŽžƒfƒBƒŒƒC)‚ð•Ô‚·(”Ä—p) + * aDelay‚ͬ‚³‚¢‚Ù‚¤‚ªUŒ‚‘¬“x‚ª‘¬‚¢ + *------------------------------------------ + */ +int status_get_adelay(struct block_list *bl) +{ + nullpo_retr(4000, bl); + if(bl->type==BL_PC && (struct map_session_data *)bl) + return (((struct map_session_data *)bl)->aspd<<1); + else { + struct status_change *sc_data=status_get_sc_data(bl); + int adelay=4000,aspd_rate = 100,i; + if(bl->type==BL_MOB && (struct mob_data *)bl) + adelay = mob_db[((struct mob_data *)bl)->class_].adelay; + else if(bl->type==BL_PET && (struct pet_data *)bl) + adelay = mob_db[((struct pet_data *)bl)->class_].adelay; + + if(sc_data) { + //ƒc[ƒnƒ“ƒhƒNƒCƒbƒPƒ“Žg—pŽž‚ŃNƒ@ƒOƒ}ƒCƒA‚Å‚àŽ„‚ð–Y‚ê‚È‚¢‚Åc‚Å‚à‚È‚¢Žž‚Í3Š„Œ¸ŽZ + if(sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ + aspd_rate -= 30; + //ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ…Žg—pŽž‚Ńc[ƒnƒ“ƒhƒNƒCƒbƒPƒ“‚Å‚àƒNƒ@ƒOƒ}ƒCƒA‚Å‚àŽ„‚ð–Y‚ê‚È‚¢‚Åc‚Å‚à‚È‚¢Žž‚Í + if(sc_data[SC_ADRENALINE].timer != -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 && + sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) { // ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… + //Žg—pŽÒ‚ƃp[ƒeƒBƒƒ“ƒo[‚ÅŠi·‚ªo‚éÝ’è‚łȂ¯‚ê‚Î3Š„Œ¸ŽZ + if(sc_data[SC_ADRENALINE].val2 || !battle_config.party_skill_penalty) + aspd_rate -= 30; + //‚»‚¤‚łȂ¯‚ê‚Î2.5Š„Œ¸ŽZ + else + aspd_rate -= 25; + } + //ƒXƒsƒAƒNƒBƒbƒPƒ“Žž‚ÍŒ¸ŽZ + if(sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 && + sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // ƒXƒsƒAƒNƒBƒbƒPƒ“ + aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2; + //—[“ú‚̃AƒTƒVƒ“ƒNƒƒXŽž‚ÍŒ¸ŽZ + if(sc_data[SC_ASSNCROS].timer!=-1 && // —[—z‚̃AƒTƒVƒ“ƒNƒƒX + sc_data[SC_TWOHANDQUICKEN].timer==-1 && sc_data[SC_ADRENALINE].timer==-1 && sc_data[SC_SPEARSQUICKEN].timer==-1 && + sc_data[SC_DONTFORGETME].timer == -1) + aspd_rate -= 5+sc_data[SC_ASSNCROS].val1+sc_data[SC_ASSNCROS].val2+sc_data[SC_ASSNCROS].val3; + //Ž„‚ð–Y‚ê‚È‚¢‚ÅcŽž‚͉ÁŽZ + if(sc_data[SC_DONTFORGETME].timer!=-1) // Ž„‚ð–Y‚ê‚È‚¢‚Å + aspd_rate += sc_data[SC_DONTFORGETME].val1*3 + sc_data[SC_DONTFORGETME].val2 + (sc_data[SC_DONTFORGETME].val3>>16); + //‹à„Žž25%‰ÁŽZ + if(sc_data[SC_STEELBODY].timer!=-1) // ‹à„ + aspd_rate += 25; + //‘‘¬ƒ|[ƒVƒ‡ƒ“Žg—pŽž‚ÍŒ¸ŽZ + if( sc_data[i=SC_SPEEDPOTION3].timer!=-1 || sc_data[i=SC_SPEEDPOTION2].timer!=-1 || sc_data[i=SC_SPEEDPOTION1].timer!=-1 || sc_data[i=SC_SPEEDPOTION0].timer!=-1) + aspd_rate -= sc_data[i].val2; + //ƒfƒBƒtƒFƒ“ƒ_[Žž‚͉ÁŽZ + if(sc_data[SC_DEFENDER].timer != -1) + aspd_rate += (25 - sc_data[SC_DEFENDER].val1*5); + //adelay += (1100 - sc_data[SC_DEFENDER].val1*100); + if(sc_data[SC_GOSPEL].timer!=-1 && + sc_data[SC_GOSPEL].val4 == BCT_ENEMY && + sc_data[SC_GOSPEL].val3 == 8) + aspd_rate = aspd_rate*125/100; + if(sc_data[SC_JOINTBEAT].timer!=-1) { + if (sc_data[SC_JOINTBEAT].val2 == 2) + aspd_rate = aspd_rate*125/100; + else if (sc_data[SC_JOINTBEAT].val2 == 3) + aspd_rate = aspd_rate*110/100; + } + } + if(aspd_rate != 100) + adelay = adelay*aspd_rate/100; + if(adelay < battle_config.monster_max_aspd<<1) adelay = battle_config.monster_max_aspd<<1; + return adelay; + } + return 4000; +} +int status_get_amotion(struct block_list *bl) +{ + nullpo_retr(2000, bl); + if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->amotion; + else { + struct status_change *sc_data=status_get_sc_data(bl); + int amotion=2000,aspd_rate = 100,i; + if(bl->type==BL_MOB && (struct mob_data *)bl) + amotion = mob_db[((struct mob_data *)bl)->class_].amotion; + else if(bl->type==BL_PET && (struct pet_data *)bl) + amotion = mob_db[((struct pet_data *)bl)->class_].amotion; + + if(sc_data) { + if(sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ + aspd_rate -= 30; + if(sc_data[SC_ADRENALINE].timer != -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 && + sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) { // ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… + if(sc_data[SC_ADRENALINE].val2 || !battle_config.party_skill_penalty) + aspd_rate -= 30; + else + aspd_rate -= 25; + } + if(sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 && + sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // ƒXƒsƒAƒNƒBƒbƒPƒ“ + aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2; + if(sc_data[SC_ASSNCROS].timer!=-1 && // —[—z‚̃AƒTƒVƒ“ƒNƒƒX + sc_data[SC_TWOHANDQUICKEN].timer==-1 && sc_data[SC_ADRENALINE].timer==-1 && sc_data[SC_SPEARSQUICKEN].timer==-1 && + sc_data[SC_DONTFORGETME].timer == -1) + aspd_rate -= 5+sc_data[SC_ASSNCROS].val1+sc_data[SC_ASSNCROS].val2+sc_data[SC_ASSNCROS].val3; + if(sc_data[SC_DONTFORGETME].timer!=-1) // Ž„‚ð–Y‚ê‚È‚¢‚Å + aspd_rate += sc_data[SC_DONTFORGETME].val1*3 + sc_data[SC_DONTFORGETME].val2 + (sc_data[SC_DONTFORGETME].val3>>16); + if(sc_data[SC_STEELBODY].timer!=-1) // ‹à„ + aspd_rate += 25; + if( sc_data[i=SC_SPEEDPOTION3].timer!=-1 || sc_data[i=SC_SPEEDPOTION2].timer!=-1 || sc_data[i=SC_SPEEDPOTION1].timer!=-1 || sc_data[i=SC_SPEEDPOTION0].timer!=-1) + aspd_rate -= sc_data[i].val2; + if(sc_data[SC_DEFENDER].timer != -1) + aspd_rate += (25 - sc_data[SC_DEFENDER].val1*5); + //amotion += (550 - sc_data[SC_DEFENDER].val1*50); + } + if(aspd_rate != 100) + amotion = amotion*aspd_rate/100; + if(amotion < battle_config.monster_max_aspd) amotion = battle_config.monster_max_aspd; + return amotion; + } + return 2000; +} +int status_get_dmotion(struct block_list *bl) +{ + int ret; + struct status_change *sc_data; + + nullpo_retr(0, bl); + sc_data = status_get_sc_data(bl); + if(bl->type==BL_MOB && (struct mob_data *)bl){ + ret=mob_db[((struct mob_data *)bl)->class_].dmotion; + if(battle_config.monster_damage_delay_rate != 100) + ret = ret*battle_config.monster_damage_delay_rate/400; + } + else if(bl->type==BL_PC && (struct map_session_data *)bl){ + ret=((struct map_session_data *)bl)->dmotion; + if(battle_config.pc_damage_delay_rate != 100) + ret = ret*battle_config.pc_damage_delay_rate/400; + } + else if(bl->type==BL_PET && (struct pet_data *)bl) + ret=mob_db[((struct pet_data *)bl)->class_].dmotion; + else + return 2000; + + if((sc_data && (sc_data[SC_ENDURE].timer!=-1 || sc_data[SC_BERSERK].timer!=-1)) || + (bl->type == BL_PC && ((struct map_session_data *)bl)->special_state.infinite_endure)) + ret=0; + + return ret; +} +int status_get_element(struct block_list *bl) +{ + int ret = 20; + struct status_change *sc_data; + + nullpo_retr(ret, bl); + sc_data = status_get_sc_data(bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) // 10‚̈ÊLv*2A‚P‚̈ʑ®« + ret=((struct mob_data *)bl)->def_ele; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + ret=20+((struct map_session_data *)bl)->def_ele; // –hŒä‘®«Lv1 + else if(bl->type==BL_PET && (struct pet_data *)bl) + ret = mob_db[((struct pet_data *)bl)->class_].element; + + if(sc_data) { + if( sc_data[SC_BENEDICTIO].timer!=-1 ) // ¹‘Ì~•Ÿ + ret=26; + if( sc_data[SC_FREEZE].timer!=-1 ) // “€Œ‹ + ret=21; + if( sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0) + ret=22; + } + + return ret; +} + +int status_get_attack_element(struct block_list *bl) +{ + int ret = 0; + struct status_change *sc_data=status_get_sc_data(bl); + + nullpo_retr(0, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + ret=0; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + ret=((struct map_session_data *)bl)->atk_ele; + else if(bl->type==BL_PET && (struct pet_data *)bl) + ret=0; + + if(sc_data) { + if( sc_data[SC_FROSTWEAPON].timer!=-1) // ƒtƒƒXƒgƒEƒFƒ|ƒ“ + ret=1; + if( sc_data[SC_SEISMICWEAPON].timer!=-1) // ƒTƒCƒYƒ~ƒbƒNƒEƒFƒ|ƒ“ + ret=2; + if( sc_data[SC_FLAMELAUNCHER].timer!=-1) // ƒtƒŒ[ƒ€ƒ‰ƒ“ƒ`ƒƒ[ + ret=3; + if( sc_data[SC_LIGHTNINGLOADER].timer!=-1) // ƒ‰ƒCƒgƒjƒ“ƒOƒ[ƒ_[ + ret=4; + if( sc_data[SC_ENCPOISON].timer!=-1) // ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“ + ret=5; + if( sc_data[SC_ASPERSIO].timer!=-1) // ƒAƒXƒyƒ‹ƒVƒI + ret=6; + } + + return ret; +} +int status_get_attack_element2(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_PC && (struct map_session_data *)bl) { + int ret = ((struct map_session_data *)bl)->atk_ele_; + struct status_change *sc_data = ((struct map_session_data *)bl)->sc_data; + + if(sc_data) { + if( sc_data[SC_FROSTWEAPON].timer!=-1) // ƒtƒƒXƒgƒEƒFƒ|ƒ“ + ret=1; + if( sc_data[SC_SEISMICWEAPON].timer!=-1) // ƒTƒCƒYƒ~ƒbƒNƒEƒFƒ|ƒ“ + ret=2; + if( sc_data[SC_FLAMELAUNCHER].timer!=-1) // ƒtƒŒ[ƒ€ƒ‰ƒ“ƒ`ƒƒ[ + ret=3; + if( sc_data[SC_LIGHTNINGLOADER].timer!=-1) // ƒ‰ƒCƒgƒjƒ“ƒOƒ[ƒ_[ + ret=4; + if( sc_data[SC_ENCPOISON].timer!=-1) // ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“ + ret=5; + if( sc_data[SC_ASPERSIO].timer!=-1) // ƒAƒXƒyƒ‹ƒVƒI + ret=6; + } + return ret; + } + return 0; +} +int status_get_party_id(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->status.party_id; + else if(bl->type==BL_MOB && (struct mob_data *)bl){ + struct mob_data *md=(struct mob_data *)bl; + if( md->master_id>0 ) + return -md->master_id; + return -md->bl.id; + } + else if(bl->type==BL_SKILL && (struct skill_unit *)bl) + return ((struct skill_unit *)bl)->group->party_id; + else + return 0; +} +int status_get_guild_id(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data *)bl)->status.guild_id; + else if(bl->type==BL_MOB && (struct mob_data *)bl) + return ((struct mob_data *)bl)->class_; + else if(bl->type==BL_SKILL && (struct skill_unit *)bl) + return ((struct skill_unit *)bl)->group->guild_id; + else + return 0; +} +int status_get_race(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return mob_db[((struct mob_data *)bl)->class_].race; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return 7; + else if(bl->type==BL_PET && (struct pet_data *)bl) + return mob_db[((struct pet_data *)bl)->class_].race; + else + return 0; +} +int status_get_size(struct block_list *bl) +{ + nullpo_retr(1, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return mob_db[((struct mob_data *)bl)->class_].size; + else if(bl->type==BL_PET && (struct pet_data *)bl) + return mob_db[((struct pet_data *)bl)->class_].size; + else if(bl->type==BL_PC) { + struct map_session_data *sd = (struct map_session_data *)bl; + //if (pc_isriding(sd)) // fact or rumour? + // return 2; + if (pc_calc_upper(sd->status.class_) == 2) + return 0; + return 1; + } else + return 1; +} +int status_get_mode(struct block_list *bl) +{ + nullpo_retr(0x01, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return mob_db[((struct mob_data *)bl)->class_].mode; + else if(bl->type==BL_PET && (struct pet_data *)bl) + return mob_db[((struct pet_data *)bl)->class_].mode; + else + return 0x01; // ‚Æ‚è‚ ‚¦‚¸“®‚‚Æ‚¢‚¤‚±‚Æ‚Å1 +} + +int status_get_mexp(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return mob_db[((struct mob_data *)bl)->class_].mexp; + else if(bl->type==BL_PET && (struct pet_data *)bl) + return mob_db[((struct pet_data *)bl)->class_].mexp; + else + return 0; +} +int status_get_race2(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type == BL_MOB && (struct mob_data *)bl) + return mob_db[((struct mob_data *)bl)->class_].race2; + else if(bl->type==BL_PET && (struct pet_data *)bl) + return mob_db[((struct pet_data *)bl)->class_].race2; + else + return 0; +} +int status_isdead(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type == BL_MOB && (struct mob_data *)bl) + return ((struct mob_data *)bl)->state.state == MS_DEAD; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return pc_isdead((struct map_session_data *)bl); + else + return 0; +} + +// StatusChangeŒn‚ÌŠ“¾ +struct status_change *status_get_sc_data(struct block_list *bl) +{ + nullpo_retr(NULL, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return ((struct mob_data*)bl)->sc_data; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return ((struct map_session_data*)bl)->sc_data; + return NULL; +} +short *status_get_sc_count(struct block_list *bl) +{ + nullpo_retr(NULL, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return &((struct mob_data*)bl)->sc_count; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return &((struct map_session_data*)bl)->sc_count; + return NULL; +} +short *status_get_opt1(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return &((struct mob_data*)bl)->opt1; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return &((struct map_session_data*)bl)->opt1; + else if(bl->type==BL_NPC && (struct npc_data *)bl) + return &((struct npc_data*)bl)->opt1; + return 0; +} +short *status_get_opt2(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return &((struct mob_data*)bl)->opt2; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return &((struct map_session_data*)bl)->opt2; + else if(bl->type==BL_NPC && (struct npc_data *)bl) + return &((struct npc_data*)bl)->opt2; + return 0; +} +short *status_get_opt3(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return &((struct mob_data*)bl)->opt3; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return &((struct map_session_data*)bl)->opt3; + else if(bl->type==BL_NPC && (struct npc_data *)bl) + return &((struct npc_data*)bl)->opt3; + return 0; +} +short *status_get_option(struct block_list *bl) +{ + nullpo_retr(0, bl); + if(bl->type==BL_MOB && (struct mob_data *)bl) + return &((struct mob_data*)bl)->option; + else if(bl->type==BL_PC && (struct map_session_data *)bl) + return &((struct map_session_data*)bl)->status.option; + else if(bl->type==BL_NPC && (struct npc_data *)bl) + return &((struct npc_data*)bl)->option; + return 0; +} + +int status_get_sc_def(struct block_list *bl, int type) +{ + int sc_def; + nullpo_retr(0, bl); + + switch (type) + { + case SP_MDEF1: // mdef + sc_def = 100 - (3 + status_get_mdef(bl) + status_get_luk(bl)/3); + break; + case SP_MDEF2: // int + sc_def = 100 - (3 + status_get_int(bl) + status_get_luk(bl)/3); + break; + case SP_DEF1: // def + sc_def = 100 - (3 + status_get_def(bl) + status_get_luk(bl)/3); + break; + case SP_DEF2: // vit + sc_def = 100 - (3 + status_get_vit(bl) + status_get_luk(bl)/3); + break; + case SP_LUK: // luck + sc_def = 100 - (3 + status_get_luk(bl)); + break; + + case SC_STONE: + case SC_FREEZE: + sc_def = 100 - (3 + status_get_mdef(bl) + status_get_luk(bl)/3); + break; + case SC_STAN: + case SC_POISON: + case SC_SILENCE: + sc_def = 100 - (3 + status_get_vit(bl) + status_get_luk(bl)/3); + break; + case SC_SLEEP: + case SC_CONFUSION: + case SC_BLIND: + sc_def = 100 - (3 + status_get_int(bl) + status_get_luk(bl)/3); + break; + case SC_CURSE: + sc_def = 100 - (3 + status_get_luk(bl)); + break; + + default: + sc_def = 100; + break; + } + + if(bl->type == BL_MOB) { + struct mob_data *md = (struct mob_data *)bl; + if (md && md->class_ == 1288) + return 0; + if (sc_def < 50) + sc_def = 50; + } else if(bl->type == BL_PC) { + struct status_change* sc_data = status_get_sc_data(bl); + if (sc_data && sc_data[SC_GOSPEL].timer != -1 && + sc_data[SC_GOSPEL].val4 == BCT_PARTY && + sc_data[SC_GOSPEL].val3 == 3) + sc_def -= 25; + } + + return (sc_def < 0) ? 0 : sc_def; +} + +/*========================================== + * ƒXƒe[ƒ^ƒXˆÙíŠJŽn + *------------------------------------------ + */ +int status_change_start(struct block_list *bl,int type,int val1,int val2,int val3,int val4,int tick,int flag) +{ + struct map_session_data *sd = NULL; + struct status_change* sc_data; + short *sc_count, *option, *opt1, *opt2, *opt3; + int opt_flag = 0, calc_flag = 0,updateflag = 0, save_flag = 0, race, mode, elem, undead_flag; + int scdef = 0; + int type2 = type; + + nullpo_retr(0, bl); + if(bl->type == BL_SKILL) + return 0; + if(bl->type == BL_MOB) + if (status_isdead(bl)) return 0; + + nullpo_retr(0, sc_data=status_get_sc_data(bl)); + nullpo_retr(0, sc_count=status_get_sc_count(bl)); + nullpo_retr(0, option=status_get_option(bl)); + nullpo_retr(0, opt1=status_get_opt1(bl)); + nullpo_retr(0, opt2=status_get_opt2(bl)); + nullpo_retr(0, opt3=status_get_opt3(bl)); + + + race=status_get_race(bl); + mode=status_get_mode(bl); + elem=status_get_elem_type(bl); + undead_flag=battle_check_undead(race,elem); + + if(type == SC_AETERNA && (sc_data[SC_STONE].timer != -1 || sc_data[SC_FREEZE].timer != -1) ) + return 0; + + switch(type){ + case SC_STONE: + case SC_FREEZE: + scdef=3+status_get_mdef(bl)+status_get_luk(bl)/3; + break; + case SC_STAN: + case SC_SILENCE: + case SC_POISON: + case SC_DPOISON: + scdef=3+status_get_vit(bl)+status_get_luk(bl)/3; + break; + case SC_SLEEP: + case SC_BLIND: + scdef=3+status_get_int(bl)+status_get_luk(bl)/3; + break; + case SC_CURSE: + scdef=3+status_get_luk(bl); + break; + +// case SC_CONFUSION: + default: + scdef=0; + } + if(scdef>=100) + return 0; + if(bl->type==BL_PC){ + sd=(struct map_session_data *)bl; + if( sd && type == SC_ADRENALINE && !(skill_get_weapontype(BS_ADRENALINE)&(1<<sd->status.weapon))) + return 0; + + if(SC_STONE<=type && type<=SC_BLIND){ /* ƒJ?ƒh‚É‚æ‚é‘Ï« */ + if( sd && sd->reseff[type-SC_STONE] > 0 && rand()%10000<sd->reseff[type-SC_STONE]){ + if(battle_config.battle_log) + printf("PC %d skill_sc_start: card‚É‚æ‚éˆÙí‘Ï«?“®\n",sd->bl.id); + return 0; + } + } + } + else if(bl->type == BL_MOB) { + } + else { + if(battle_config.error_log) + printf("status_change_start: neither MOB nor PC !\n"); + return 0; + } + + if(type==SC_FREEZE && undead_flag && !(flag&1)) + return 0; + + if (type==SC_BLESSING && (bl->type==BL_PC || (!undead_flag && race!=6))) { + if (sc_data[SC_CURSE].timer!=-1) + status_change_end(bl,SC_CURSE,-1); + if (sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0) + status_change_end(bl,SC_STONE,-1); + } + + if((type == SC_ADRENALINE || type == SC_WEAPONPERFECTION || type == SC_OVERTHRUST) && + sc_data[type].timer != -1 && sc_data[type].val2 && !val2) + return 0; + + if(mode & 0x20 && (type==SC_STONE || type==SC_FREEZE || + type==SC_STAN || type==SC_SLEEP || type==SC_SILENCE || type==SC_QUAGMIRE || type == SC_DECREASEAGI || type == SC_SIGNUMCRUCIS || type == SC_PROVOKE || + (type == SC_BLESSING && (undead_flag || race == 6))) && !(flag&1)){ + /* ƒ{ƒX‚É‚Í?‚©‚È‚¢(‚½‚¾‚µƒJ?ƒh‚É‚æ‚é?‰Ê‚Í“K—p‚³‚ê‚é) */ + return 0; + } + if(type==SC_FREEZE || type==SC_STAN || type==SC_SLEEP) + battle_stopwalking(bl,1); + + if(sc_data[type].timer != -1){ /* ‚·‚łɓ¯‚¶ˆÙí‚ɂȂÁ‚Ä‚¢‚éꇃ^ƒCƒ}‰ðœ */ + if(sc_data[type].val1 > val1 && type != SC_COMBO && type != SC_DANCING && type != SC_DEVOTION && + type != SC_SPEEDPOTION0 && type != SC_SPEEDPOTION1 && type != SC_SPEEDPOTION2 && type != SC_SPEEDPOTION3 + && type != SC_ATKPOT && type != SC_MATKPOT) // added atk and matk potions [Valaris] + return 0; + + if ((type >=SC_STAN && type <= SC_BLIND) || type == SC_DPOISON) + return 0;/* ?‚¬‘«‚µ‚ª‚Å‚«‚È‚¢?‘ÔˆÙí‚Å‚ ‚鎞‚Í?‘ÔˆÙí‚ðs‚í‚È‚¢ */ + + (*sc_count)--; + delete_timer(sc_data[type].timer, status_change_timer); + sc_data[type].timer = -1; + } + + // ƒNƒAƒOƒ}ƒCƒA/Ž„‚ð–Y‚ê‚È‚¢‚Å’†‚Í–³Œø‚ȃXƒLƒ‹ + if ((sc_data[SC_QUAGMIRE].timer!=-1 || sc_data[SC_DONTFORGETME].timer!=-1) && + (type==SC_CONCENTRATE || type==SC_INCREASEAGI || + type==SC_TWOHANDQUICKEN || type==SC_SPEARSQUICKEN || + type==SC_ADRENALINE || type==SC_LOUD || type==SC_TRUESIGHT || + type==SC_WINDWALK || type==SC_CARTBOOST || type==SC_ASSNCROS)) + return 0; + + switch(type){ /* ˆÙí‚ÌŽí—Þ‚²‚Æ‚Ì?— */ + case SC_PROVOKE: /* ƒvƒƒ{ƒbƒN */ + calc_flag = 1; + if(tick <= 0) tick = 1000; /* (ƒI?ƒgƒo?ƒT?ƒN) */ + break; + case SC_ENDURE: /* ƒCƒ“ƒfƒ…ƒA */ + if(tick <= 0) tick = 1000 * 60; + calc_flag = 1; // for updating mdef +#ifdef TWILIGHT + val2 = 40; // [Celest] +#else + val2 = 7; // [Celest] +#endif + break; + case SC_AUTOBERSERK: + { + tick = 60*1000; + if (bl->type == BL_PC && sd->status.hp<sd->status.max_hp>>2 && + (sc_data[SC_PROVOKE].timer==-1 || sc_data[SC_PROVOKE].val2==0)) + status_change_start(bl,SC_PROVOKE,10,1,0,0,0,0); + } + break; + + case SC_CONCENTRATE: /* W’†—ÍŒüã */ + case SC_BLESSING: /* ƒuƒŒƒbƒVƒ“ƒO */ + case SC_ANGELUS: /* ƒAƒ“ƒ[ƒ‹ƒX */ + calc_flag = 1; + break; + + case SC_INCREASEAGI: /* ‘¬“x㸠*/ + calc_flag = 1; + if(sc_data[SC_DECREASEAGI].timer!=-1 ) + status_change_end(bl,SC_DECREASEAGI,-1); + // the effect will still remain [celest] +// if(sc_data[SC_WINDWALK].timer!=-1 ) /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ +// status_change_end(bl,SC_WINDWALK,-1); + break; + case SC_DECREASEAGI: /* ‘¬“xŒ¸ */ + if (bl->type == BL_PC) // Celest + tick>>=1; + calc_flag = 1; + if(sc_data[SC_INCREASEAGI].timer!=-1 ) + status_change_end(bl,SC_INCREASEAGI,-1); + if(sc_data[SC_ADRENALINE].timer!=-1 ) + status_change_end(bl,SC_ADRENALINE,-1); + if(sc_data[SC_SPEARSQUICKEN].timer!=-1 ) + status_change_end(bl,SC_SPEARSQUICKEN,-1); + if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 ) + status_change_end(bl,SC_TWOHANDQUICKEN,-1); + break; + case SC_SIGNUMCRUCIS: /* ƒVƒOƒiƒ€ƒNƒ‹ƒVƒX */ + calc_flag = 1; +// val2 = 14 + val1; + val2 = 10 + val1*2; + tick = 600*1000; + clif_emotion(bl,4); + break; + case SC_SLOWPOISON: + if (sc_data[SC_POISON].timer == -1 && sc_data[SC_DPOISON].timer == -1) + return 0; + break; + case SC_TWOHANDQUICKEN: /* 2HQ */ + if(sc_data[SC_DECREASEAGI].timer!=-1) + return 0; + *opt3 |= 1; + calc_flag = 1; + break; + case SC_ADRENALINE: /* ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… */ + if(sc_data[SC_DECREASEAGI].timer!=-1) + return 0; + if(bl->type == BL_PC) + if(pc_checkskill(sd,BS_HILTBINDING)>0) + tick += tick / 10; + calc_flag = 1; + break; + case SC_WEAPONPERFECTION: /* ƒEƒFƒ|ƒ“ƒp?ƒtƒFƒNƒVƒ‡ƒ“ */ + if(bl->type == BL_PC) + if(pc_checkskill(sd,BS_HILTBINDING)>0) + tick += tick / 10; + break; + case SC_OVERTHRUST: /* ƒI?ƒo?ƒXƒ‰ƒXƒg */ + if(bl->type == BL_PC) + if(pc_checkskill(sd,BS_HILTBINDING)>0) + tick += tick / 10; + *opt3 |= 2; + break; + case SC_MAXIMIZEPOWER: /* ƒ}ƒLƒVƒ}ƒCƒYƒpƒ?(SP‚ª1Œ¸‚鎞ŠÔ,val2‚É‚à) */ + if(bl->type == BL_PC) + val2 = tick; + else + tick = 5000*val1; + break; + case SC_ENCPOISON: /* ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“ */ + calc_flag = 1; + val2=(((val1 - 1) / 2) + 3)*100; /* “Å•t?Šm—¦ */ + skill_enchant_elemental_end(bl,SC_ENCPOISON); + break; + case SC_EDP: // [Celest] + val2 = val1 + 2; /* –Ò“Å•t?Šm—¦(%) */ + calc_flag = 1; + break; + case SC_POISONREACT: /* ƒ|ƒCƒYƒ“ƒŠƒAƒNƒg */ + val2=val1/2 + val1%2; // [Celest] + break; + case SC_IMPOSITIO: /* ƒCƒ“ƒ|ƒVƒeƒBƒIƒ}ƒkƒX */ + calc_flag = 1; + break; + case SC_ASPERSIO: /* ƒAƒXƒyƒ‹ƒVƒI */ + skill_enchant_elemental_end(bl,SC_ASPERSIO); + break; + case SC_SUFFRAGIUM: /* ƒTƒtƒ‰ƒMƒ€ */ + case SC_BENEDICTIO: /* ¹? */ + case SC_MAGNIFICAT: /* ƒ}ƒOƒjƒtƒBƒJ?ƒg */ + case SC_AETERNA: /* ƒG?ƒeƒ‹ƒi */ + break; + case SC_ENERGYCOAT: /* ƒGƒiƒW?ƒR?ƒg */ + *opt3 |= 4; + break; + case SC_MAGICROD: + val2 = val1*20; + break; + case SC_KYRIE: /* ƒLƒŠƒGƒGƒŒƒCƒ\ƒ“ */ + val2 = status_get_max_hp(bl) * (val1 * 2 + 10) / 100;/* ‘Ï‹v“x */ + val3 = (val1 / 2 + 5); /* ‰ñ? */ +// -- moonsoul (added to undo assumptio status if target has it) + if(sc_data[SC_ASSUMPTIO].timer!=-1 ) + status_change_end(bl,SC_ASSUMPTIO,-1); + break; + case SC_MINDBREAKER: + calc_flag = 1; + if(tick <= 0) tick = 1000; /* (ƒI?ƒgƒo?ƒT?ƒN) */ + case SC_GLORIA: /* ƒOƒƒŠƒA */ + calc_flag = 1; + break; + case SC_LOUD: /* ƒ‰ƒEƒhƒ{ƒCƒX */ + calc_flag = 1; + break; + case SC_TRICKDEAD: /* Ž€‚ñ‚¾‚Ó‚è */ + if (bl->type == BL_PC) { + pc_stopattack((struct map_session_data *)sd); + } + break; + case SC_QUAGMIRE: /* ƒNƒ@ƒOƒ}ƒCƒA */ + calc_flag = 1; + if(sc_data[SC_CONCENTRATE].timer!=-1 ) /* W’†—ÍŒüã‰ðœ */ + status_change_end(bl,SC_CONCENTRATE,-1); + if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* ‘¬“x㸉ðœ */ + status_change_end(bl,SC_INCREASEAGI,-1); + if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 ) + status_change_end(bl,SC_TWOHANDQUICKEN,-1); + if(sc_data[SC_SPEARSQUICKEN].timer!=-1 ) + status_change_end(bl,SC_SPEARSQUICKEN,-1); + if(sc_data[SC_ADRENALINE].timer!=-1 ) + status_change_end(bl,SC_ADRENALINE,-1); + if(sc_data[SC_LOUD].timer!=-1 ) + status_change_end(bl,SC_LOUD,-1); + if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* ƒgƒDƒ‹?ƒTƒCƒg */ + status_change_end(bl,SC_TRUESIGHT,-1); + if(sc_data[SC_WINDWALK].timer!=-1 ) /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ + status_change_end(bl,SC_WINDWALK,-1); + if(sc_data[SC_CARTBOOST].timer!=-1 ) /* ƒJ?ƒgƒu?ƒXƒg */ + status_change_end(bl,SC_CARTBOOST,-1); + break; + case SC_MAGICPOWER: + calc_flag = 1; + val2 = 1; + break; + case SC_SACRIFICE: + val2 = 5; + break; + case SC_FLAMELAUNCHER: /* ƒtƒŒ?ƒ€ƒ‰ƒ“ƒ`ƒƒ? */ + skill_enchant_elemental_end(bl,SC_FLAMELAUNCHER); + break; + case SC_FROSTWEAPON: /* ƒtƒƒXƒgƒEƒFƒ|ƒ“ */ + skill_enchant_elemental_end(bl,SC_FROSTWEAPON); + break; + case SC_LIGHTNINGLOADER: /* ƒ‰ƒCƒgƒjƒ“ƒOƒ?ƒ_? */ + skill_enchant_elemental_end(bl,SC_LIGHTNINGLOADER); + break; + case SC_SEISMICWEAPON: /* ƒTƒCƒYƒ~ƒbƒNƒEƒFƒ|ƒ“ */ + skill_enchant_elemental_end(bl,SC_SEISMICWEAPON); + break; + case SC_DEVOTION: /* ƒfƒBƒ{?ƒVƒ‡ƒ“ */ + calc_flag = 1; + break; + case SC_PROVIDENCE: /* ƒvƒƒ”ƒBƒfƒ“ƒX */ + calc_flag = 1; + val2=val1*5; + break; + case SC_REFLECTSHIELD: + val2=10+val1*3; + break; + case SC_STRIPWEAPON: + if (val2==0) val2=90; + break; + case SC_STRIPSHIELD: + if (val2==0) val2=85; + break; + case SC_STRIPARMOR: + case SC_STRIPHELM: + case SC_CP_WEAPON: + case SC_CP_SHIELD: + case SC_CP_ARMOR: + case SC_CP_HELM: + break; + + case SC_AUTOSPELL: /* ƒI?ƒgƒXƒyƒ‹ */ + val4 = 5 + val1*2; + break; + + case SC_VOLCANO: + calc_flag = 1; + val3 = val1*10; + //val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) ); + break; + case SC_DELUGE: + calc_flag = 1; + //val3 = val1>=5?15: (val1==4?14: (val1==3?12: ( val1==2?9:5 ) ) ); + //val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) ); + if (sc_data[SC_FOGWALL].timer != -1 && sc_data[SC_BLIND].timer != -1) + status_change_end(bl,SC_BLIND,-1); + break; + case SC_VIOLENTGALE: + calc_flag = 1; + val3 = val1*3; + //val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) ); + break; + + case SC_SPEARSQUICKEN: /* ƒXƒsƒAƒNƒCƒbƒPƒ“ */ + calc_flag = 1; + val2 = 20+val1; + *opt3 |= 1; + break; + case SC_COMBO: + break; + case SC_BLADESTOP_WAIT: /* ”’nŽæ‚è(‘Ò‚¿) */ + break; + case SC_BLADESTOP: /* ”’nŽæ‚è */ + if(val2==2) clif_bladestop((struct block_list *)val3,(struct block_list *)val4,1); + *opt3 |= 32; + break; + + case SC_LULLABY: /* ŽqŽç‰S */ + val2 = 11; + break; + case SC_RICHMANKIM: + break; + case SC_ETERNALCHAOS: /* ƒGƒ^?ƒiƒ‹ƒJƒIƒX */ + calc_flag = 1; + break; + case SC_DRUMBATTLE: /* ?‘¾ŒÛ‚Ì‹¿‚« */ + calc_flag = 1; + val2 = (val1+1)*25; + val3 = (val1+1)*2; + break; + case SC_NIBELUNGEN: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ + calc_flag = 1; + //val2 = (val1+2)*50; + val3 = (val1+2)*25; + break; + case SC_ROKISWEIL: /* ƒƒL‚Ì‹©‚Ñ */ + break; + case SC_INTOABYSS: /* [•£‚Ì’†‚É */ + break; + case SC_SIEGFRIED: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ + calc_flag = 1; + val2 = 55 + val1*5; + val3 = val1*10; + break; + case SC_DISSONANCE: /* •s‹¦˜a‰¹ */ + val2 = 10; + break; + case SC_WHISTLE: /* Œû“J */ + calc_flag = 1; + break; + case SC_ASSNCROS: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX */ + calc_flag = 1; + break; + case SC_POEMBRAGI: /* ƒuƒ‰ƒM‚ÌŽ */ + break; + case SC_APPLEIDUN: /* ƒCƒhƒDƒ“‚Ì—ÑŒç */ + calc_flag = 1; + break; + case SC_UGLYDANCE: /* Ž©•ªŸŽè‚ȃ_ƒ“ƒX */ + val2 = 10; + break; + case SC_HUMMING: /* ƒnƒ~ƒ“ƒO */ + calc_flag = 1; + break; + case SC_DONTFORGETME: /* Ž„‚ð–Y‚ê‚È‚¢‚Å */ + calc_flag = 1; + if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* ‘¬“x㸉ðœ */ + status_change_end(bl,SC_INCREASEAGI,-1); + if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 ) + status_change_end(bl,SC_TWOHANDQUICKEN,-1); + if(sc_data[SC_SPEARSQUICKEN].timer!=-1 ) + status_change_end(bl,SC_SPEARSQUICKEN,-1); + if(sc_data[SC_ADRENALINE].timer!=-1 ) + status_change_end(bl,SC_ADRENALINE,-1); + if(sc_data[SC_ASSNCROS].timer!=-1 ) + status_change_end(bl,SC_ASSNCROS,-1); + if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* ƒgƒDƒ‹?ƒTƒCƒg */ + status_change_end(bl,SC_TRUESIGHT,-1); + if(sc_data[SC_WINDWALK].timer!=-1 ) /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ + status_change_end(bl,SC_WINDWALK,-1); + if(sc_data[SC_CARTBOOST].timer!=-1 ) /* ƒJ?ƒgƒu?ƒXƒg */ + status_change_end(bl,SC_CARTBOOST,-1); + break; + case SC_FORTUNE: /* K‰^‚̃LƒX */ + calc_flag = 1; + break; + case SC_SERVICE4U: /* ƒT?ƒrƒXƒtƒH?ƒ†? */ + calc_flag = 1; + break; + case SC_MOONLIT: + val2 = bl->id; + break; + case SC_DANCING: /* ƒ_ƒ“ƒX/‰‰‘t’† */ + calc_flag = 1; + val3= tick / 1000; + tick = 1000; + break; + + case SC_EXPLOSIONSPIRITS: // ”š—ô”g“® + calc_flag = 1; + val2 = 75 + 25*val1; + *opt3 |= 8; + break; + case SC_STEELBODY: // ‹à„ + calc_flag = 1; + *opt3 |= 16; + break; + case SC_EXTREMITYFIST: /* ˆ¢C—…”e™€Œ */ + break; + case SC_AUTOCOUNTER: + val3 = val4 = 0; + break; + + case SC_SPEEDPOTION0: /* ?‘¬ƒ|?ƒVƒ‡ƒ“ */ + case SC_SPEEDPOTION1: + case SC_SPEEDPOTION2: + case SC_SPEEDPOTION3: + calc_flag = 1; + tick = 1000 * tick; + val2 = 5*(2+type-SC_SPEEDPOTION0); + break; + + /* atk & matk potions [Valaris] */ + case SC_ATKPOT: + case SC_MATKPOT: + calc_flag = 1; + tick = 1000 * tick; + break; + case SC_WEDDING: //Œ‹¥—p(Œ‹¥ˆßւɂȂÁ‚Ä?‚‚Ì‚ª?‚¢‚Æ‚©) + { + time_t timer; + + calc_flag = 1; + tick = 10000; + if(!val2) + val2 = time(&timer); + } + break; + case SC_NOCHAT: //ƒ`ƒƒƒbƒg‹ÖŽ~?‘Ô + { + time_t timer; + + if(!battle_config.muting_players) + break; + + tick = 60000; + if(!val2) + val2 = time(&timer); + updateflag = SP_MANNER; + save_flag = 1; // celest + } + break; + case SC_SELFDESTRUCTION: //Ž©”š + clif_skillcasting(bl,bl->id, bl->id,0,0,331,skill_get_time(val2,val1)); + val3 = tick / 1000; + tick = 1000; + break; + + /* option1 */ + case SC_STONE: /* Ή» */ + if(!(flag&2)) { + int sc_def = status_get_mdef(bl)*200; + tick = tick - sc_def; + } + val3 = tick/1000; + if(val3 < 1) val3 = 1; + tick = 5000; + val2 = 1; + break; + case SC_SLEEP: /* ‡–° */ + if(!(flag&2)) { +// int sc_def = 100 - (status_get_int(bl) + status_get_luk(bl)/3); +// tick = tick * sc_def / 100; +// if(tick < 1000) tick = 1000; + tick = 30000;//‡–°‚̓Xƒe?ƒ^ƒX‘Ï«‚É?‚í‚炸30•b + } + break; + case SC_FREEZE: /* “€Œ‹ */ + if(!(flag&2)) { + int sc_def = 100 - status_get_mdef(bl); + tick = tick * sc_def / 100; + } + break; + case SC_STAN: /* ƒXƒ^ƒ“ival2‚Ƀ~ƒŠ•bƒZƒbƒgj */ + if(!(flag&2)) { + int sc_def = status_get_sc_def_vit(bl); + tick = tick * sc_def / 100; + } + break; + + /* option2 */ + case SC_DPOISON: /* –Ò“Å */ + { + int mhp = status_get_max_hp(bl); + int hp = status_get_hp(bl); + // MHP?1/4???????? + if (hp > mhp>>2) { + if(bl->type == BL_PC) { + int diff = mhp*10/100; + if (hp - diff < mhp>>2) + hp = hp - (mhp>>2); + pc_heal((struct map_session_data *)bl, -hp, 0); + } else if(bl->type == BL_MOB) { + struct mob_data *md = (struct mob_data *)bl; + hp -= mhp*15/100; + if (hp > mhp>>2) + md->hp = hp; + else + md->hp = mhp>>2; + } + } + } // fall through + case SC_POISON: /* “Å */ + calc_flag = 1; + if(!(flag&2)) { + int sc_def = 100 - (status_get_vit(bl) + status_get_luk(bl)/5); + tick = tick * sc_def / 100; + } + val3 = tick/1000; + if(val3 < 1) val3 = 1; + tick = 1000; + break; + case SC_SILENCE: /* ’¾?iƒŒƒbƒNƒXƒfƒr?ƒij */ + if (sc_data && sc_data[SC_GOSPEL].timer!=-1) { + skill_delunitgroup((struct skill_unit_group *)sc_data[SC_GOSPEL].val3); + status_change_end(bl,SC_GOSPEL,-1); + break; + } + if(!(flag&2)) { + int sc_def = 100 - status_get_vit(bl); + tick = tick * sc_def / 100; + } + break; + case SC_CONFUSION: + val2 = tick; + tick = 100; + clif_emotion(bl,1); + if (sd) { + pc_stop_walking (sd, 0); + } + break; + case SC_BLIND: /* ˆÃ? */ + calc_flag = 1; + if(!(flag&2)) { + int sc_def = status_get_lv(bl)/10 + status_get_int(bl)/15; + tick = 30000 - sc_def; + } + break; + case SC_CURSE: + calc_flag = 1; + if(!(flag&2)) { + int sc_def = 100 - status_get_vit(bl); + tick = tick * sc_def / 100; + } + break; + + /* option */ + case SC_HIDING: /* ƒnƒCƒfƒBƒ“ƒO */ + calc_flag = 1; + if(bl->type == BL_PC) { + val2 = tick / 1000; /* Ž?ŽžŠÔ */ + tick = 1000; + } + break; + case SC_CHASEWALK: + case SC_CLOAKING: /* ƒNƒ?ƒLƒ“ƒO */ + if(bl->type == BL_PC) { + calc_flag = 1; // [Celest] + val2 = tick; + val3 = type==SC_CLOAKING ? 130-val1*3 : 135-val1*5; + } + else + tick = 5000*val1; + break; + case SC_SIGHT: /* ƒTƒCƒg/ƒ‹ƒAƒt */ + case SC_RUWACH: + val2 = tick/250; + tick = 10; + break; + + /* ƒZ?ƒtƒeƒBƒEƒH?ƒ‹Aƒjƒ…?ƒ} */ + case SC_SAFETYWALL: case SC_PNEUMA: + tick=((struct skill_unit *)val2)->group->limit; + break; + + /* ƒAƒ“ƒNƒ‹ */ + case SC_ANKLE: + break; + + /* ƒXƒLƒ‹‚¶‚á‚È‚¢/ŽžŠÔ‚É?ŒW‚µ‚È‚¢ */ + case SC_RIDING: + calc_flag = 1; + tick = 600*1000; + break; + case SC_FALCON: + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_BROKNWEAPON: + case SC_BROKNARMOR: + tick=600*1000; + break; + + case SC_AUTOGUARD: + { + int i,t; + for(i=val2=0;i<val1;i++) { + t = 5-(i>>1); + val2 += (t < 0)? 1:t; + } + } + break; + + case SC_DEFENDER: + calc_flag = 1; + val2 = 5 + val1*15; + break; + + case SC_KEEPING: + case SC_BARRIER: + calc_flag = 1; + + case SC_HALLUCINATION: + break; + + case SC_CONCENTRATION: /* ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ */ + *opt3 |= 1; + calc_flag = 1; + break; + + case SC_TENSIONRELAX: /* ƒeƒ“ƒVƒ‡ƒ“ƒŠƒ‰ƒbƒNƒX */ + if(bl->type == BL_PC) { + tick = 10000; + } else return 0; + break; + + case SC_AURABLADE: /* ƒI?ƒ‰ƒuƒŒ?ƒh */ + case SC_PARRYING: /* ƒpƒŠƒCƒ“ƒO */ +// case SC_ASSUMPTIO: /* */ +// case SC_HEADCRUSH: /* ƒwƒbƒhƒNƒ‰ƒbƒVƒ… */ +// case SC_JOINTBEAT: /* ƒWƒ‡ƒCƒ“ƒgƒr?ƒg */ +// case SC_MARIONETTE: /* ƒ}ƒŠƒIƒlƒbƒgƒRƒ“ƒgƒ?ƒ‹ */ + + //‚Æ‚è‚ ‚¦‚¸Žè?‚« + break; + +// -- moonsoul (for new upper class related skill status effects) +/* + case SC_AURABLADE: + val2 = val1*10; + break; + case SC_PARRYING: + val2=val1*3; + break; + case SC_CONCENTRATION: + calc_flag=1; + val2=val1*10; + val3=val1*5; + break; + case SC_TENSIONRELAX: +// val2 = 10; +// val3 = 15; + break; + case SC_BERSERK: + calc_flag=1; + break; + case SC_ASSUMPTIO: + if(sc_data[SC_KYRIE].timer!=-1 ) + status_change_end(bl,SC_KYRIE,-1); + break;*/ + + case SC_WINDWALK: /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ + calc_flag = 1; + val2 = (val1 / 2); //Flee㸗¦ + break; + + case SC_JOINTBEAT: // Random break [DracoRPG] + calc_flag = 1; + val2 = rand()%6 + 1; + if (val2 == 6) status_change_start(bl,SC_BLEEDING,val1,0,0,0,skill_get_time2(type,val1),0); + break; + + case SC_BERSERK: /* ƒo?ƒT?ƒN */ + if(sd){ + sd->status.hp = sd->status.max_hp * 3; + sd->status.sp = 0; + clif_updatestatus(sd,SP_HP); + clif_updatestatus(sd,SP_SP); + clif_status_change(bl,SC_INCREASEAGI,1); /* ƒAƒCƒRƒ“•\ަ */ + sd->canregen_tick = gettick() + 300000; + } + *opt3 |= 128; + tick = 10000; + calc_flag = 1; + break; + + case SC_ASSUMPTIO: /* ƒAƒXƒ€ƒvƒeƒBƒI */ + if(sc_data[SC_KYRIE].timer!=-1 ) + status_change_end(bl,SC_KYRIE,-1); + break; + *opt3 |= 2048; + break; + + case SC_BASILICA: // [celest] + break; + + case SC_GOSPEL: + if (val4 == BCT_SELF) { // self effect + int i; + if (sd) { + sd->canact_tick += tick; + sd->canmove_tick += tick; + } + val2 = tick; + tick = 1000; + for (i=0; i<=26; i++) { + if(sc_data[i].timer!=-1) + status_change_end(bl,i,-1); + } + for (i=58; i<=62; i++) { + if(sc_data[i].timer!=-1) + status_change_end(bl,i,-1); + } + for (i=132; i<=136; i++) { + if(sc_data[i].timer!=-1) + status_change_end(bl,i,-1); + } + } + break; + + case SC_MARIONETTE: /* ƒ}ƒŠƒIƒlƒbƒgƒRƒ“ƒgƒ?ƒ‹ */ + case SC_MARIONETTE2: + val2 = tick; + if (!val3) + return 0; + tick = 1000; + calc_flag = 1; + *opt3 |= 1024; + break; + + case SC_MELTDOWN: /* ƒƒ‹ƒgƒ_ƒEƒ“ */ + case SC_CARTBOOST: /* ƒJ?ƒgƒu?ƒXƒg */ + case SC_TRUESIGHT: /* ƒgƒDƒ‹?ƒTƒCƒg */ + case SC_SPIDERWEB: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ + calc_flag = 1; + break; + + case SC_REJECTSWORD: /* ƒŠƒWƒFƒNƒgƒ\?ƒh */ + val2 = 3; //3‰ñU?‚𒵂˕Ԃ· + break; + + case SC_MEMORIZE: /* ƒƒ‚ƒ‰ƒCƒY */ + val2 = 5; //‰ñ‰r¥‚ð1/3‚É‚·‚é + break; + + case SC_SPLASHER: /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ? */ + break; + + case SC_FOGWALL: + break; + + case SC_PRESERVE: + break; + + case SC_BLEEDING: + { + // every 1 vit deducts 1 second + val3 = tick - status_get_vit(bl) * 1000; + // minimum 50 seconds + if (val3 < 50000) + val3 = 50000; + val4 = 10000; + tick = 1000; + } + break; + + case SC_SLOWDOWN: + case SC_SPEEDUP0: + calc_flag = 1; + break; + + case SC_REGENERATION: + val1 = 2; + case SC_BATTLEORDERS: + tick = 60000; // 1 minute + calc_flag = 1; + break; + + case SC_GUILDAURA: + calc_flag = 1; + tick = 1000; + break; + + case SC_BABY: + type2 = _SC_BABY; + break; + + default: + if(battle_config.error_log) + printf("UnknownStatusChange [%d]\n", type); + return 0; + } + + if(bl->type==BL_PC && + (type<SC_SENDMAX || type==SC_PRESERVE || type==SC_BATTLEORDERS || type==SC_BABY)) + clif_status_change(bl,type2,1); /* ƒAƒCƒRƒ“•\ަ */ + + /* option‚Ì?X */ + switch(type){ + case SC_STONE: + case SC_FREEZE: + case SC_STAN: + case SC_SLEEP: + battle_stopattack(bl); /* U?’âŽ~ */ + skill_stop_dancing(bl,0); /* ‰‰‘t/ƒ_ƒ“ƒX‚Ì’†? */ + { /* “¯Žž‚ÉŠ|‚©‚ç‚È‚¢ƒXƒe?ƒ^ƒXˆÙí‚ð‰ðœ */ + int i; + for(i = SC_STONE; i <= SC_SLEEP; i++){ + if(sc_data[i].timer != -1){ + (*sc_count)--; + delete_timer(sc_data[i].timer, status_change_timer); + sc_data[i].timer = -1; + } + } + } + if(type == SC_STONE) + *opt1 = 6; + else + *opt1 = type - SC_STONE + 1; + opt_flag = 1; + break; + case SC_POISON: + case SC_CURSE: + case SC_SILENCE: + case SC_BLIND: + *opt2 |= 1<<(type-SC_POISON); + opt_flag = 1; + break; + case SC_DPOISON: // Žb’肜ł̃GƒtƒFƒNƒg‚ðŽg—p + *opt2 |= 1; + opt_flag = 1; + break; + case SC_SIGNUMCRUCIS: + *opt2 |= 0x40; + opt_flag = 1; + break; + case SC_HIDING: + case SC_CLOAKING: + battle_stopattack(bl); /* U?’âŽ~ */ + *option |= ((type==SC_HIDING)?2:4); + opt_flag =1 ; + break; + case SC_CHASEWALK: + battle_stopattack(bl); /* U?’âŽ~ */ + *option |= 16388; + opt_flag =1 ; + break; + case SC_SIGHT: + *option |= 1; + opt_flag = 1; + break; + case SC_RUWACH: + *option |= 8192; + opt_flag = 1; + break; + case SC_WEDDING: + *option |= 4096; + opt_flag = 1; + } + + if(opt_flag) /* option‚Ì?X */ + clif_changeoption(bl); + + (*sc_count)++; /* ƒXƒe?ƒ^ƒXˆÙí‚Ì? */ + + sc_data[type].val1 = val1; + sc_data[type].val2 = val2; + sc_data[type].val3 = val3; + sc_data[type].val4 = val4; + /* ƒ^ƒCƒ}?Ý’è */ + sc_data[type].timer = add_timer( + gettick() + tick, status_change_timer, bl->id, type); + + if(bl->type==BL_PC && calc_flag) + status_calc_pc(sd,0); /* ƒXƒe?ƒ^ƒXÄŒvŽZ */ + + if(bl->type==BL_PC && save_flag) + chrif_save(sd); // save the player status + + if(bl->type==BL_PC && updateflag) + clif_updatestatus(sd,updateflag); /* ƒXƒe?ƒ^ƒX‚ðƒNƒ‰ƒCƒAƒ“ƒg‚É‘—‚é */ + + return 0; +} +/*========================================== + * ƒXƒe[ƒ^ƒXˆÙí‘S‰ðœ + *------------------------------------------ + */ +int status_change_clear(struct block_list *bl,int type) +{ + struct status_change* sc_data; + short *sc_count, *option, *opt1, *opt2, *opt3; + int i; + + nullpo_retr(0, bl); + nullpo_retr(0, sc_data = status_get_sc_data(bl)); + nullpo_retr(0, sc_count = status_get_sc_count(bl)); + nullpo_retr(0, option = status_get_option(bl)); + nullpo_retr(0, opt1 = status_get_opt1(bl)); + nullpo_retr(0, opt2 = status_get_opt2(bl)); + nullpo_retr(0, opt3 = status_get_opt3(bl)); + + if (*sc_count == 0) + return 0; + for(i = 0; i < MAX_STATUSCHANGE; i++){ + if(sc_data[i].timer != -1){ /* ˆÙ킪‚ ‚é‚È‚çƒ^ƒCƒ}?‚ð휂·‚é */ + status_change_end(bl, i, -1); + } + } + *sc_count = 0; + *opt1 = 0; + *opt2 = 0; + *opt3 = 0; + *option &= OPTION_MASK; + + if (night_flag == 1 && type == BL_PC && !map[bl->m].flag.indoors && // by [Yor] + !map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) // [celest] + *opt2 |= STATE_BLIND; + + if(!type || type&2) + clif_changeoption(bl); + + return 0; +} + +/*========================================== + * ƒXƒe[ƒ^ƒXˆÙíI—¹ + *------------------------------------------ + */ +int status_change_end( struct block_list* bl , int type,int tid ) +{ + struct status_change* sc_data; + int opt_flag=0, calc_flag = 0; + short *sc_count, *option, *opt1, *opt2, *opt3; + int type2 = type; + + nullpo_retr(0, bl); + if(bl->type!=BL_PC && bl->type!=BL_MOB) { + if(battle_config.error_log) + printf("status_change_end: neither MOB nor PC !\n"); + return 0; + } + nullpo_retr(0, sc_data = status_get_sc_data(bl)); + nullpo_retr(0, sc_count = status_get_sc_count(bl)); + nullpo_retr(0, option = status_get_option(bl)); + nullpo_retr(0, opt1 = status_get_opt1(bl)); + nullpo_retr(0, opt2 = status_get_opt2(bl)); + nullpo_retr(0, opt3 = status_get_opt3(bl)); + + if ((*sc_count) > 0 && sc_data[type].timer != -1 && (sc_data[type].timer == tid || tid == -1)) { + + if (tid == -1) // ƒ^ƒCƒ}‚©‚çŒÄ‚΂ê‚Ä‚¢‚È‚¢‚È‚çƒ^ƒCƒ}íœ‚ð‚·‚é + delete_timer(sc_data[type].timer,status_change_timer); + + /* ŠY?‚̈Ùí‚ð³í‚É?‚· */ + sc_data[type].timer=-1; + (*sc_count)--; + + switch(type){ /* ˆÙí‚ÌŽí—Þ‚²‚Æ‚Ì?— */ + case SC_PROVOKE: /* ƒvƒƒ{ƒbƒN */ + case SC_ENDURE: // celest + case SC_CONCENTRATE: /* W’†—ÍŒüã */ + case SC_BLESSING: /* ƒuƒŒƒbƒVƒ“ƒO */ + case SC_ANGELUS: /* ƒAƒ“ƒ[ƒ‹ƒX */ + case SC_INCREASEAGI: /* ‘¬“x㸠*/ + case SC_DECREASEAGI: /* ‘¬“xŒ¸ */ + case SC_SIGNUMCRUCIS: /* ƒVƒOƒiƒ€ƒNƒ‹ƒVƒX */ + case SC_HIDING: + case SC_TWOHANDQUICKEN: /* 2HQ */ + case SC_ADRENALINE: /* ƒAƒhƒŒƒiƒŠƒ“ƒ‰ƒbƒVƒ… */ + case SC_ENCPOISON: /* ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“ */ + case SC_IMPOSITIO: /* ƒCƒ“ƒ|ƒVƒeƒBƒIƒ}ƒkƒX */ + case SC_GLORIA: /* ƒOƒƒŠƒA */ + case SC_LOUD: /* ƒ‰ƒEƒhƒ{ƒCƒX */ + case SC_QUAGMIRE: /* ƒNƒ@ƒOƒ}ƒCƒA */ + case SC_PROVIDENCE: /* ƒvƒƒ”ƒBƒfƒ“ƒX */ + case SC_SPEARSQUICKEN: /* ƒXƒsƒAƒNƒCƒbƒPƒ“ */ + case SC_VOLCANO: + case SC_DELUGE: + case SC_VIOLENTGALE: + case SC_ETERNALCHAOS: /* ƒGƒ^?ƒiƒ‹ƒJƒIƒX */ + case SC_DRUMBATTLE: /* ?‘¾ŒÛ‚Ì‹¿‚« */ + case SC_NIBELUNGEN: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö */ + case SC_SIEGFRIED: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh */ + case SC_WHISTLE: /* Œû“J */ + case SC_ASSNCROS: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX */ + case SC_HUMMING: /* ƒnƒ~ƒ“ƒO */ + case SC_DONTFORGETME: /* Ž„‚ð–Y‚ê‚È‚¢‚Å */ + case SC_FORTUNE: /* K‰^‚̃LƒX */ + case SC_SERVICE4U: /* ƒT?ƒrƒXƒtƒH?ƒ†? */ + case SC_EXPLOSIONSPIRITS: // ”š—ô”g“® + case SC_STEELBODY: // ‹à„ + case SC_DEFENDER: + case SC_SPEEDPOTION0: /* ?‘¬ƒ|?ƒVƒ‡ƒ“ */ + case SC_SPEEDPOTION1: + case SC_SPEEDPOTION2: + case SC_SPEEDPOTION3: + case SC_APPLEIDUN: /* ƒCƒhƒDƒ“‚Ì—ÑŒç */ + case SC_RIDING: + case SC_BLADESTOP_WAIT: + case SC_CONCENTRATION: /* ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ */ + case SC_ASSUMPTIO: /* ƒAƒVƒƒƒ“ƒvƒeƒBƒI */ + case SC_WINDWALK: /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ + case SC_TRUESIGHT: /* ƒgƒDƒ‹?ƒTƒCƒg */ + case SC_SPIDERWEB: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ + case SC_MAGICPOWER: /* –‚–@—Í?• */ + case SC_CHASEWALK: + case SC_ATKPOT: /* attack potion [Valaris] */ + case SC_MATKPOT: /* magic attack potion [Valaris] */ + case SC_WEDDING: //Œ‹¥—p(Œ‹¥ˆßւɂȂÁ‚Ä?‚‚Ì‚ª?‚¢‚Æ‚©) + case SC_MELTDOWN: /* ƒƒ‹ƒgƒ_ƒEƒ“ */ + case SC_MINDBREAKER: /* ƒ}ƒCƒ“ƒhƒuƒŒ[ƒJ[ */ + // Celest + case SC_EDP: + case SC_SLOWDOWN: + case SC_SPEEDUP0: + case SC_BATTLEORDERS: + case SC_REGENERATION: + case SC_GUILDAURA: + calc_flag = 1; + break; + case SC_AUTOBERSERK: + if (sc_data[SC_PROVOKE].timer != -1) + status_change_end(bl,SC_PROVOKE,-1); + break; + case SC_BERSERK: /* ƒo?ƒT?ƒN */ + calc_flag = 1; + clif_status_change(bl,SC_INCREASEAGI,0); /* ƒAƒCƒRƒ“Á‹Ž */ + break; + case SC_DEVOTION: /* ƒfƒBƒ{?ƒVƒ‡ƒ“ */ + { + struct map_session_data *md = map_id2sd(sc_data[type].val1); + sc_data[type].val1=sc_data[type].val2=0; + skill_devotion(md,bl->id); + calc_flag = 1; + } + break; + case SC_BLADESTOP: + { + struct status_change *t_sc_data = status_get_sc_data((struct block_list *)sc_data[type].val4); + //•Еû‚ªØ‚ꂽ‚Ì‚Å‘ŠŽè‚Ì”’n?‘Ô‚ªØ‚ê‚ĂȂ¢‚̂Ȃç‰ðœ + if(t_sc_data && t_sc_data[SC_BLADESTOP].timer!=-1) + status_change_end((struct block_list *)sc_data[type].val4,SC_BLADESTOP,-1); + + if(sc_data[type].val2==2) + clif_bladestop((struct block_list *)sc_data[type].val3,(struct block_list *)sc_data[type].val4,0); + } + break; + case SC_DANCING: + { + struct map_session_data *dsd; + struct status_change *d_sc_data; + if(sc_data[type].val4 && (dsd=map_id2sd(sc_data[type].val4))){ + d_sc_data = dsd->sc_data; + //‡‘t‚Å‘ŠŽè‚ª‚¢‚éê‡‘ŠŽè‚Ìval4‚ð0‚É‚·‚é + if(d_sc_data && d_sc_data[type].timer!=-1) + d_sc_data[type].val4=0; + } + } + calc_flag = 1; + break; + case SC_NOCHAT: //ƒ`ƒƒƒbƒg‹ÖŽ~?‘Ô + { + struct map_session_data *sd=NULL; + if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)){ + if (sd->status.manner >= 0) // weeee ^^ [celest] + sd->status.manner = 0; + clif_updatestatus(sd,SP_MANNER); + } + } + break; + case SC_SPLASHER: /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ? */ + { + struct block_list *src=map_id2bl(sc_data[type].val3); + if(src && tid!=-1){ + //Ž©•ª‚Ƀ_ƒ?ƒW•Žü?3*3‚Ƀ_ƒ?ƒW + skill_castend_damage_id(src, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 ); + } + } + break; + case SC_SELFDESTRUCTION: /* Ž©”š */ + { + //Ž©•ª‚̃_ƒ?ƒW‚Í0‚É‚µ‚Ä + struct mob_data *md=NULL; + if(bl->type == BL_MOB && (md=(struct mob_data*)bl)) + skill_castend_damage_id(bl, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 ); + } + break; + /* option1 */ + case SC_FREEZE: + sc_data[type].val3 = 0; + break; + + /* option2 */ + case SC_POISON: /* “Å */ + case SC_BLIND: /* ˆÃ? */ + case SC_CURSE: + calc_flag = 1; + break; + + // celest + case SC_CONFUSION: + { + struct map_session_data *sd=NULL; + if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)){ + sd->next_walktime = -1; + } + } + break; + + case SC_MARIONETTE: /* ƒ}ƒŠƒIƒlƒbƒgƒRƒ“ƒgƒ?ƒ‹ */ + case SC_MARIONETTE2: /// Marionette target + { + // check for partner and end their marionette status as well + int type2 = (type == SC_MARIONETTE) ? SC_MARIONETTE2 : SC_MARIONETTE; + struct block_list *pbl = map_id2bl(sc_data[type].val3); + if (pbl) { + struct status_change* sc_data; + if (*status_get_sc_count(pbl) > 0 && + (sc_data = status_get_sc_data(pbl)) && + sc_data[type2].timer != -1) + status_change_end(pbl, type2, -1); + } + calc_flag = 1; + } + break; + + case SC_BABY: + type2 = _SC_BABY; + break; + } + + if(bl->type==BL_PC && + (type<SC_SENDMAX || type==SC_PRESERVE || type==SC_BATTLEORDERS || type==SC_BABY)) + clif_status_change(bl,type2,0); /* ƒAƒCƒRƒ“Á‹Ž */ + + switch(type){ /* ³í‚É?‚邯‚«‚Ȃɂ©?—‚ª•K—v */ + case SC_STONE: + case SC_FREEZE: + case SC_STAN: + case SC_SLEEP: + *opt1 = 0; + opt_flag = 1; + break; + + case SC_POISON: + if (sc_data[SC_DPOISON].timer != -1) // + break; // DPOISON—p‚̃IƒvƒVƒ‡ƒ“ + *opt2 &= ~1; // ‚ª?—p‚É—pˆÓ‚³‚ê‚½ê‡‚É‚Í + opt_flag = 1; // ‚±‚±‚Í휂·‚é + break; // + case SC_CURSE: + case SC_SILENCE: + case SC_BLIND: + *opt2 &= ~(1<<(type-SC_POISON)); + opt_flag = 1; + break; + case SC_DPOISON: + if (sc_data[SC_POISON].timer != -1) // DPOISON—p‚̃IƒvƒVƒ‡ƒ“‚ª + break; // —pˆÓ‚³‚ꂽ‚çíœ + *opt2 &= ~1; // “Å?‘Ô‰ðœ + opt_flag = 1; + break; + case SC_SIGNUMCRUCIS: + *opt2 &= ~0x40; + opt_flag = 1; + break; + + case SC_HIDING: + case SC_CLOAKING: + *option &= ~((type == SC_HIDING) ? 2 : 4); + calc_flag = 1; // orn + opt_flag = 1 ; + break; + + case SC_CHASEWALK: + *option &= ~16388; + opt_flag = 1 ; + break; + + case SC_SIGHT: + *option &= ~1; + opt_flag = 1; + break; + case SC_WEDDING: //Œ‹¥—p(Œ‹¥ˆßւɂȂÁ‚Ä?‚‚Ì‚ª?‚¢‚Æ‚©) + *option &= ~4096; + opt_flag = 1; + break; + case SC_RUWACH: + *option &= ~8192; + opt_flag = 1; + break; + + //opt3 + case SC_TWOHANDQUICKEN: /* 2HQ */ + case SC_SPEARSQUICKEN: /* ƒXƒsƒAƒNƒCƒbƒPƒ“ */ + case SC_CONCENTRATION: /* ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ */ + *opt3 &= ~1; + break; + case SC_OVERTHRUST: /* ƒI?ƒo?ƒXƒ‰ƒXƒg */ + *opt3 &= ~2; + break; + case SC_ENERGYCOAT: /* ƒGƒiƒW?ƒR?ƒg */ + *opt3 &= ~4; + break; + case SC_EXPLOSIONSPIRITS: // ”š—ô”g“® + *opt3 &= ~8; + break; + case SC_STEELBODY: // ‹à„ + *opt3 &= ~16; + break; + case SC_BLADESTOP: /* ”’nŽæ‚è */ + *opt3 &= ~32; + break; + case SC_BERSERK: /* ƒo?ƒT?ƒN */ + *opt3 &= ~128; + break; + case SC_MARIONETTE: /* ƒ}ƒŠƒIƒlƒbƒgƒRƒ“ƒgƒ?ƒ‹ */ + case SC_MARIONETTE2: + *opt3 &= ~1024; + break; + case SC_ASSUMPTIO: /* ƒAƒXƒ€ƒvƒeƒBƒI */ + *opt3 &= ~2048; + break; + } + + if (night_flag == 1 && (*opt2 & STATE_BLIND) == 0 && bl->type == BL_PC && // by [Yor] + !map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) { // [celest] + *opt2 |= STATE_BLIND; + opt_flag = 1; + } + + if(opt_flag) /* option‚Ì?X‚ð?‚¦‚é */ + clif_changeoption(bl); + + if (bl->type == BL_PC && calc_flag) + status_calc_pc((struct map_session_data *)bl,0); /* ƒXƒe?ƒ^ƒXÄŒvŽZ */ + } + + return 0; +} + + +/*========================================== + * ƒXƒe[ƒ^ƒXˆÙíI—¹ƒ^ƒCƒ}[ + *------------------------------------------ + */ +int status_change_timer(int tid, unsigned int tick, int id, int data) +{ + int type = data; + struct block_list *bl; + struct map_session_data *sd=NULL; + struct status_change *sc_data; + //short *sc_count; //Žg‚Á‚ĂȂ¢H + +// security system to prevent forgetting timer removal + int temp_timerid; + + bl=map_id2bl(id); +#ifndef _WIN32 + nullpo_retr_f(0, bl, "id=%d data=%d",id,data); +#endif + nullpo_retr(0, sc_data=status_get_sc_data(bl)); + + if(bl->type==BL_PC) + nullpo_retr(0, sd=(struct map_session_data *)bl); + + //sc_count=status_get_sc_count(bl); //Žg‚Á‚ĂȂ¢H + + if(sc_data[type].timer != tid) { + if(battle_config.error_log) + printf("status_change_timer %d != %d\n",tid,sc_data[type].timer); + return 0; + } + + // security system to prevent forgetting timer removal + // you shouldn't be that careless inside the switch here + temp_timerid = sc_data[type].timer; + sc_data[type].timer = -1; + + switch(type){ /* “ÁŽê‚È?—‚ɂȂéê‡ */ + case SC_MAXIMIZEPOWER: /* ƒ}ƒLƒVƒ}ƒCƒYƒpƒ? */ + case SC_CLOAKING: + if(sd){ + if( sd->status.sp > 0 ){ /* SPØ‚ê‚é‚܂Ŏ? */ + sd->status.sp--; + clif_updatestatus(sd,SP_SP); + sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ + sc_data[type].val2+tick, status_change_timer, bl->id, data); + return 0; + } + } + break; + + case SC_CHASEWALK: + if(sd){ + int sp = 10+sc_data[SC_CHASEWALK].val1*2; + if (map[sd->bl.m].flag.gvg) sp *= 5; + if( sd->status.sp > sp){ + sd->status.sp -= sp; // update sp cost [Celest] + clif_updatestatus(sd,SP_SP); + sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ + sc_data[type].val2+tick, status_change_timer, bl->id, data); + sc_data[SC_CHASEWALK].val4++; + if (sc_data[SC_CHASEWALK].val4 > 3) + sc_data[SC_CHASEWALK].val4 = 0; + status_calc_pc (sd, 0); + return 0; + } + } + break; + + case SC_HIDING: /* ƒnƒCƒfƒBƒ“ƒO */ + if(sd){ /* SP‚ª‚ ‚Á‚ÄAŽžŠÔ§ŒÀ‚ÌŠÔ‚ÍŽ? */ + if( sd->status.sp > 0 && (--sc_data[type].val2)>0 ){ + if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){ + sd->status.sp--; + clif_updatestatus(sd,SP_SP); + } + sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ + 1000+tick, status_change_timer, + bl->id, data); + return 0; + } + } + break; + + case SC_SIGHT: /* ƒTƒCƒg */ + case SC_RUWACH: /* ƒ‹ƒAƒt */ + { + int range = 5; + if ( type == SC_SIGHT ) range = 7; + map_foreachinarea( status_change_timer_sub, + bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0, + bl,type,tick); + + if( (--sc_data[type].val2)>0 ){ + sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ + 250+tick, status_change_timer, + bl->id, data); + return 0; + } + } + break; + + case SC_SIGNUMCRUCIS: /* ƒVƒOƒiƒ€ƒNƒ‹ƒVƒX */ + { + int race = status_get_race(bl); + if(race == 6 || battle_check_undead(race,status_get_elem_type(bl))) { + sc_data[type].timer=add_timer(1000*600+tick,status_change_timer, bl->id, data ); + return 0; + } + } + break; + + case SC_PROVOKE: /* ƒvƒƒ{ƒbƒN/ƒI?ƒgƒo?ƒT?ƒN */ + if(sc_data[type].val2!=0){ /* ƒI?ƒgƒo?ƒT?ƒNi‚P•b‚²‚Æ‚ÉHPƒ`ƒFƒbƒNj */ + if(sd && sd->status.hp>sd->status.max_hp>>2) /* ’âŽ~ */ + break; + sc_data[type].timer=add_timer( 1000+tick,status_change_timer, bl->id, data ); + return 0; + } + break; + + case SC_ENDURE: /* ƒCƒ“ƒfƒ…ƒA */ + case SC_AUTOBERSERK: // Celest + if(sd && sd->special_state.infinite_endure) { +#ifdef TWILIGHT + sc_data[type].timer=add_timer( 1000*600+tick,status_change_timer, bl->id, data ); +#else + sc_data[type].timer=add_timer( 1000*60+tick,status_change_timer, bl->id, data ); +#endif + //sc_data[type].val2=1; + return 0; + } + break; + + case SC_DISSONANCE: /* •s‹¦˜a‰¹ */ + if( (--sc_data[type].val2)>0){ + struct skill_unit *unit= + (struct skill_unit *)sc_data[type].val4; + struct block_list *src; + /*if(!unit || !unit->group) + break; + src=map_id2bl(unit->group->src_id); + if(!src) + break;*/ + nullpo_retb(unit); + nullpo_retb(unit->group); + nullpo_retb(src=map_id2bl(unit->group->src_id)); + skill_attack(BF_MISC,src,&unit->bl,bl,unit->group->skill_id,sc_data[type].val1,tick,0); + if( (bl->type==BL_MOB) && (MS_DEAD==((struct mob_data *)bl)->state.state) ) + break; + sc_data[type].timer=add_timer(skill_get_time2(unit->group->skill_id,unit->group->skill_lv)+tick, + status_change_timer, bl->id, data ); + return 0; + } + break; + + case SC_LULLABY: /* ŽqŽç‰S */ + if( (--sc_data[type].val2)>0){ + struct skill_unit *unit= + (struct skill_unit *)sc_data[type].val4; + nullpo_retb(unit); + nullpo_retb(unit->group); + if(unit->group->src_id == bl->id) + break; + skill_additional_effect(bl,bl,unit->group->skill_id,sc_data[type].val1,BF_LONG|BF_SKILL|BF_MISC,tick); + if (unit->group != 0) + { + sc_data[type].timer=add_timer(skill_get_time(unit->group->skill_id,unit->group->skill_lv)/10+tick, + status_change_timer, bl->id, data ); + return 0; + }// dont forget the brackets + } + break; + + case SC_STONE: + if(sc_data[type].val2 != 0) { + short *opt1 = status_get_opt1(bl); + sc_data[type].val2 = 0; + sc_data[type].val4 = 0; + battle_stopwalking(bl,1); + if(opt1) { + *opt1 = 1; + clif_changeoption(bl); + } + sc_data[type].timer=add_timer(1000+tick,status_change_timer, bl->id, data ); + return 0; + } + else if( (--sc_data[type].val3) > 0) { + int hp = status_get_max_hp(bl); + if((++sc_data[type].val4)%5 == 0 && status_get_hp(bl) > hp>>2) { + hp = hp/100; + if(hp < 1) hp = 1; + if(sd) + pc_heal(sd,-hp,0); + else if(bl->type == BL_MOB){ + struct mob_data *md; + if((md=((struct mob_data *)bl)) == NULL) + break; + md->hp -= hp; + } + } + sc_data[type].timer=add_timer(1000+tick,status_change_timer, bl->id, data ); + return 0; + } + break; + + case SC_POISON: + case SC_DPOISON: + if (sc_data[SC_SLOWPOISON].timer == -1 && (--sc_data[type].val3) > 0) { + int hp = status_get_max_hp(bl); + if (type == SC_POISON && status_get_hp(bl) < hp>>2) + break; + if(sd) { + hp = (type == SC_DPOISON) ? 3 + hp/50 : 3 + hp*3/200; + pc_heal(sd, -hp, 0); + } else if (bl->type == BL_MOB) { + struct mob_data *md; + nullpo_retr(0, md=(struct mob_data *)bl); + hp = (type == SC_DPOISON) ? 3 + hp/100 : 3 + hp/200; + md->hp -= hp; + } + } + if (sc_data[type].val3 > 0) + { + sc_data[type].timer=add_timer(1000+tick,status_change_timer, bl->id, data ); + // hmm setting up a timer and breaking then to call status_change_end just right away? + // I think you're missing brackets and a: + return 0; + } + break; + + case SC_TENSIONRELAX: /* ƒeƒ“ƒVƒ‡ƒ“ƒŠƒ‰ƒbƒNƒX */ + if(sd){ /* SP‚ª‚ ‚Á‚ÄAHP‚ª?ƒ^ƒ“‚łȂ¯‚ê‚Î?? */ + if( sd->status.sp > 12 && sd->status.max_hp > sd->status.hp ){ +/* if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){ + sd->status.sp -= 12; + clif_updatestatus(sd,SP_SP); + } */ + sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ + 10000+tick, status_change_timer, + bl->id, data); + return 0; + } + if(sd->status.max_hp <= sd->status.hp) + { + status_change_end(&sd->bl,SC_TENSIONRELAX,-1); + // calling status_change_end then break and call it again might not be that what is necessary + // or am I wrong? + // so I just add brackets and a: + return 0; + } + } + break; + case SC_BLEEDING: // [celest] + // i hope i haven't interpreted it wrong.. which i might ^^; + // Source: + // - 10õ©ª´ªÈªËHPª¬Êõá´ + // - õóúìªÎªÞªÞ«µ?«Ðì¹ÔѪä«ê«í«°ª·ªÆªâ?ÍýªÏἪ¨ªÊª¤ + if((sc_data[type].val3 -= 1000) > 0) { + if((sc_data[type].val4 -= 1000) > 0) { + int hp = rand()%300+400; + if(sd) { + pc_heal(sd,-hp,0); + sd->canmove_tick = tick+1000; + } + else if(bl->type == BL_MOB) { + struct mob_data *md; + nullpo_retr(0, md=(struct mob_data *)bl); + md->hp -= hp; + } + } + if (sd) { + sd->canact_tick = tick+1000; + } + + sc_data[type].timer=add_timer(1000+tick,status_change_timer, bl->id, data ); + // hmm setting up a timer and breaking then to call status_change_end just right away? + // I think you're missing a: + return 0; + } + break; + + /* ŽžŠÔ؂ꖳ‚µHH */ + case SC_AETERNA: + case SC_TRICKDEAD: + case SC_RIDING: + case SC_FALCON: + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_MAGICPOWER: /* –‚–@—Í?• */ + case SC_REJECTSWORD: /* ƒŠƒWƒFƒNƒgƒ\?ƒh */ + case SC_MEMORIZE: /* ƒƒ‚ƒ‰ƒCƒY */ + case SC_BROKNWEAPON: + case SC_BROKNARMOR: + case SC_SACRIFICE: + sc_data[type].timer=add_timer( 1000*600+tick,status_change_timer, bl->id, data ); + return 0; + + case SC_DANCING: //ƒ_ƒ“ƒXƒXƒLƒ‹‚ÌŽžŠÔSPÁ”ï + { + int s=0; + if(sd){ + if(sd->status.sp > 0 && (--sc_data[type].val3)>0){ + switch(sc_data[type].val1){ + case BD_RICHMANKIM: /* ƒjƒˆƒ‹ƒh‚̉ƒ 3•b‚ÉSP1 */ + case BD_DRUMBATTLEFIELD: /* ?‘¾ŒÛ‚Ì‹¿‚« 3•b‚ÉSP1 */ + case BD_RINGNIBELUNGEN: /* ƒj?ƒxƒ‹ƒ“ƒO‚ÌŽw—Ö 3•b‚ÉSP1 */ + case BD_SIEGFRIED: /* •sŽ€g‚̃W?ƒNƒtƒŠ?ƒh 3•b‚ÉSP1 */ + case BA_DISSONANCE: /* •s‹¦˜a‰¹ 3•b‚ÅSP1 */ + case BA_ASSASSINCROSS: /* —[—z‚̃AƒTƒVƒ“ƒNƒƒX 3•b‚ÅSP1 */ + case DC_UGLYDANCE: /* Ž©•ªŸŽè‚ȃ_ƒ“ƒX 3•b‚ÅSP1 */ + s=3; + break; + case BD_LULLABY: /* ŽqŽç‰Ì 4•b‚ÉSP1 */ + case BD_ETERNALCHAOS: /* ‰i‰“‚̬“× 4•b‚ÉSP1 */ + case BD_ROKISWEIL: /* ƒƒL‚Ì‹©‚Ñ 4•b‚ÉSP1 */ + case DC_FORTUNEKISS: /* K‰^‚̃LƒX 4•b‚ÅSP1 */ + s=4; + break; + case BD_INTOABYSS: /* [•£‚Ì’†‚É 5•b‚ÉSP1 */ + case BA_WHISTLE: /* Œû“J 5•b‚ÅSP1 */ + case DC_HUMMING: /* ƒnƒ~ƒ“ƒO 5•b‚ÅSP1 */ + case BA_POEMBRAGI: /* ƒuƒ‰ƒM‚ÌŽ 5•b‚ÅSP1 */ + case DC_SERVICEFORYOU: /* ƒT?ƒrƒXƒtƒH?ƒ†? 5•b‚ÅSP1 */ + s=5; + break; + case BA_APPLEIDUN: /* ƒCƒhƒDƒ“‚Ì—ÑŒç 6•b‚ÅSP1 */ + s=6; + break; + case DC_DONTFORGETME: /* Ž„‚ð–Y‚ê‚È‚¢‚Åc 10•b‚ÅSP1 */ + case CG_MOONLIT: /* ŒŽ–¾‚è‚Ìò‚É—Ž‚¿‚é‰Ô‚Ñ‚ç 10•b‚ÅSP1H */ + s=10; + break; + } + if(s && ((sc_data[type].val3 % s) == 0)){ + sd->status.sp--; + clif_updatestatus(sd,SP_SP); + } + sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ + 1000+tick, status_change_timer, + bl->id, data); + return 0; + } + } + } + break; + case SC_BERSERK: /* ƒo?ƒT?ƒN */ + if(sd){ /* HP‚ª100ˆÈã‚È‚ç?? */ + if( (sd->status.hp - sd->status.max_hp*5/100) > 100 ){ // 5% every 10 seconds [DracoRPG] + sd->status.hp -= sd->status.max_hp*5/100; // changed to max hp [celest] + clif_updatestatus(sd,SP_HP); + sc_data[type].timer = add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ + 10000+tick, status_change_timer, + bl->id, data); + return 0; + } + } + break; + case SC_WEDDING: //Œ‹¥—p(Œ‹¥ˆßւɂȂÁ‚Ä?‚‚Ì‚ª?‚¢‚Æ‚©) + if(sd){ + time_t timer; + if(time(&timer) < ((sc_data[type].val2) + 3600)){ //1ŽžŠÔ‚½‚Á‚Ä‚¢‚È‚¢‚Ì‚Å?? + sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ + 10000+tick, status_change_timer, + bl->id, data); + return 0; + } + } + break; + case SC_NOCHAT: //ƒ`ƒƒƒbƒg‹ÖŽ~?‘Ô + if(sd && battle_config.muting_players){ + time_t timer; + if((++sd->status.manner) && time(&timer) < ((sc_data[type].val2) + 60*(0-sd->status.manner))){ //ŠJŽn‚©‚çstatus.manner•ª?‚Á‚ĂȂ¢‚Ì‚Å?? + clif_updatestatus(sd,SP_MANNER); + sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è(60•b) */ + 60000+tick, status_change_timer, + bl->id, data); + return 0; + } + } + break; + case SC_SELFDESTRUCTION: /* Ž©”š */ + if(--sc_data[type].val3>0){ + struct mob_data *md; + if(bl->type==BL_MOB && (md=(struct mob_data *)bl) && md->speed > 250){ + md->speed -= 250; + md->next_walktime=tick; + } + sc_data[type].timer=add_timer( /* ƒ^ƒCƒ}?ÄÝ’è */ + 1000+tick, status_change_timer, + bl->id, data); + return 0; + } + break; + + case SC_SPLASHER: + if (sc_data[type].val4 % 1000 == 0) { + char timer[2]; + sprintf (timer, "%d", sc_data[type].val4/1000); + clif_message(bl, timer); + } + if((sc_data[type].val4 -= 500) > 0) { + sc_data[type].timer = add_timer( + 500 + tick, status_change_timer, + bl->id, data); + return 0; + } + break; + + case SC_MARIONETTE: /* ƒ}ƒŠƒIƒlƒbƒgƒRƒ“ƒgƒ?ƒ‹ */ + case SC_MARIONETTE2: + { + struct block_list *pbl = map_id2bl(sc_data[type].val3); + if (pbl && battle_check_range(bl, pbl, 7) && + (sc_data[type].val2 -= 1000)>0) { + sc_data[type].timer = add_timer( + 1000 + tick, status_change_timer, + bl->id, data); + return 0; + } + } + break; + + // Celest + case SC_CONFUSION: + { + int i = 3000; + //struct mob_data *md; + if (sd) { + pc_randomwalk (sd, gettick()); + sd->next_walktime = tick + (i=1000 + rand()%1000); + } /*else if (bl->type==BL_MOB && (md=(struct mob_data *)bl) && md->mode&1 && mob_can_move(md)) { + md->state.state=MS_WALK; + if( DIFF_TICK(md->next_walktime,tick) > + 7000 && + (md->walkpath.path_len==0 || md->walkpath.path_pos>=md->walkpath.path_len) ) + md->next_walktime = tick + 3000*rand()%2000; + mob_randomwalk(md,tick); + }*/ + if ((sc_data[type].val2 -= 1000) > 0) { + sc_data[type].timer = add_timer( + i + tick, status_change_timer, + bl->id, data); + return 0; + } + } + break; + + case SC_GOSPEL: + { + int calc_flag = 0; + if (sc_data[type].val3 > 0) { + sc_data[type].val3 = 0; + calc_flag = 1; + } + if(sd && sc_data[type].val4 == BCT_SELF){ + int hp, sp; + hp = (sc_data[type].val1 > 5) ? 45 : 30; + sp = (sc_data[type].val1 > 5) ? 35 : 20; + if(sd->status.hp - hp > 0 && + sd->status.sp - sp > 0){ + sd->status.hp -= hp; + sd->status.sp -= sp; + clif_updatestatus(sd,SP_HP); + clif_updatestatus(sd,SP_SP); + if ((sc_data[type].val2 -= 10000) > 0) { + sc_data[type].timer = add_timer( + 10000+tick, status_change_timer, + bl->id, data); + return 0; + } + } + } else if (sd && sc_data[type].val4 == BCT_PARTY) { + int i; + switch ((i = rand() % 12)) { + case 1: // heal between 100-1000 + { + struct block_list tbl; + int heal = rand() % 900 + 100; + tbl.id = 0; + tbl.m = bl->m; + tbl.x = bl->x; + tbl.y = bl->y; + clif_skill_nodamage(&tbl,bl,AL_HEAL,heal,1); + battle_heal(NULL,bl,heal,0,0); + } + break; + case 2: // end negative status + { + int j; + for (j=0; j<4; j++) + if(sc_data[i + SC_POISON].timer!=-1) { + status_change_end(bl,j,-1); + break; + } + } + break; + case 3: // +25% resistance to negative status + case 4: // +25% max hp + case 5: // +25% max sp + case 6: // +2 to all stats + case 11: // +25% armor and vit def + case 12: // +8% atk + case 13: // +5% flee + case 14: // +5% hit + sc_data[type].val3 = i; + if (i == 6 || + (i >= 11 && i <= 14)) + calc_flag = 1; + break; + case 7: // level 5 bless + { + struct block_list tbl; + tbl.id = 0; + tbl.m = bl->m; + tbl.x = bl->x; + tbl.y = bl->y; + clif_skill_nodamage(&tbl,bl,AL_BLESSING,5,1); + status_change_start(bl,SkillStatusChangeTable[AL_BLESSING],5,0,0,0,10000,0 ); + } + break; + case 8: // level 5 increase agility + { + struct block_list tbl; + tbl.id = 0; + tbl.m = bl->m; + tbl.x = bl->x; + tbl.y = bl->y; + clif_skill_nodamage(&tbl,bl,AL_INCAGI,5,1); + status_change_start(bl,SkillStatusChangeTable[AL_INCAGI],5,0,0,0,10000,0 ); + } + break; + case 9: // holy element to weapon + { + struct block_list tbl; + tbl.id = 0; + tbl.m = bl->m; + tbl.x = bl->x; + tbl.y = bl->y; + clif_skill_nodamage(&tbl,bl,PR_ASPERSIO,1,1); + status_change_start(bl,SkillStatusChangeTable[PR_ASPERSIO],1,0,0,0,10000,0 ); + } + break; + case 10: // holy element to armour + { + struct block_list tbl; + tbl.id = 0; + tbl.m = bl->m; + tbl.x = bl->x; + tbl.y = bl->y; + clif_skill_nodamage(&tbl,bl,PR_BENEDICTIO,1,1); + status_change_start(bl,SkillStatusChangeTable[PR_BENEDICTIO],1,0,0,0,10000,0 ); + } + break; + default: + break; + } + } else if (sc_data[type].val4 == BCT_ENEMY) { + int i; + switch ((i = rand() % 8)) { + case 1: // damage between 300-800 + case 2: // damage between 150-550 (ignore def) + battle_damage(NULL, bl, rand() % 500,0); // temporary damage + break; + case 3: // random status effect + { + int effect[3] = { + SC_CURSE, + SC_BLIND, + SC_POISON }; + status_change_start(bl,effect[rand()%3],1,0,0,0,10000,0 ); + } + break; + case 4: // level 10 provoke + { + struct block_list tbl; + tbl.id = 0; + tbl.m = bl->m; + tbl.x = bl->x; + tbl.y = bl->y; + clif_skill_nodamage(&tbl,bl,SM_PROVOKE,1,1); + status_change_start(bl,SkillStatusChangeTable[SM_PROVOKE],10,0,0,0,10000,0 ); + } + break; + case 5: // 0 def + case 6: // 0 atk + case 7: // 0 flee + case 8: // -75% move speed and aspd + sc_data[type].val3 = i; + calc_flag = 1; + break; + default: + break; + } + } + if (sd && calc_flag) + status_calc_pc (sd, 0); + } + break; + + case SC_GUILDAURA: + { + struct block_list *tbl = map_id2bl(sc_data[type].val2); + + if (tbl && battle_check_range(bl, tbl, 2)){ + sc_data[type].timer = add_timer( + 1000 + tick, status_change_timer, + bl->id, data); + return 0; + }// ugh, don't forget the brackets + } + break; + } + + // default for all non-handled control paths + // security system to prevent forgetting timer removal + + // if we reach this point we need the timer for the next call, + // so restore it to have status_change_end handle a valid timer + sc_data[type].timer = temp_timerid; + + return status_change_end( bl,type,tid ); +} + +/*========================================== + * ƒXƒe[ƒ^ƒXˆÙíƒ^ƒCƒ}[”͈͈— + *------------------------------------------ + */ +int status_change_timer_sub(struct block_list *bl, va_list ap ) +{ + struct block_list *src; + int type; + unsigned int tick; + + nullpo_retr(0, bl); + nullpo_retr(0, ap); + nullpo_retr(0, src=va_arg(ap,struct block_list*)); + type=va_arg(ap,int); + tick=va_arg(ap,unsigned int); + + if(bl->type!=BL_PC && bl->type!=BL_MOB) + return 0; + + switch( type ){ + case SC_SIGHT: /* ƒTƒCƒg */ + case SC_CONCENTRATE: + if( (*status_get_option(bl))&6 ){ + status_change_end( bl, SC_HIDING, -1); + status_change_end( bl, SC_CLOAKING, -1); + } + break; + case SC_RUWACH: /* ƒ‹ƒAƒt */ + if( (*status_get_option(bl))&6 ){ + struct status_change *sc_data = status_get_sc_data(bl); // check whether the target is hiding/cloaking [celest] + if (sc_data && (sc_data[SC_HIDING].timer != -1 || // if the target is using a special hiding, i.e not using normal hiding/cloaking, don't bother + sc_data[SC_CLOAKING].timer != -1)) { + status_change_end( bl, SC_HIDING, -1); + status_change_end( bl, SC_CLOAKING, -1); + } + if(battle_check_target( src,bl, BCT_ENEMY ) > 0) + skill_attack(BF_MAGIC,src,src,bl,AL_RUWACH,sc_data[type].val1,tick,0); + } + break; + } + return 0; +} + + +static int status_calc_sigma(void) +{ + int i,j,k; + + for(i=0;i<MAX_PC_CLASS;i++) { + memset(hp_sigma_val[i],0,sizeof(hp_sigma_val[i])); + for(k=0,j=2;j<=MAX_LEVEL;j++) { + k += hp_coefficient[i]*j + 50; + k -= k%100; + hp_sigma_val[i][j-1] = k; + } + } + return 0; +} + +int status_readdb(void) { + int i,j,k; + FILE *fp; + char line[1024],*p; + + // JOB•â³?’l‚P + fp=fopen("db/job_db1.txt","r"); + if(fp==NULL){ + printf("can't read db/job_db1.txt\n"); + return 1; + } + i=0; + while(fgets(line, sizeof(line)-1, fp)){ + char *split[50]; + if(line[0]=='/' && line[1]=='/') + continue; + for(j=0,p=line;j<21 && p;j++){ + split[j]=p; + p=strchr(p,','); + if(p) *p++=0; + } + if(j<21) + continue; + max_weight_base[i]=atoi(split[0]); + hp_coefficient[i]=atoi(split[1]); + hp_coefficient2[i]=atoi(split[2]); + sp_coefficient[i]=atoi(split[3]); + for(j=0;j<17;j++) + aspd_base[i][j]=atoi(split[j+4]); + i++; +// -- moonsoul (below two lines added to accommodate high numbered new class ids) + if(i==24) + i=4001; + if(i==MAX_PC_CLASS) + break; + } + fclose(fp); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/job_db1.txt"); + ShowStatus(tmp_output); + + // JOBƒ{?ƒiƒX + memset(job_bonus,0,sizeof(job_bonus)); + fp=fopen("db/job_db2.txt","r"); + if(fp==NULL){ + printf("can't read db/job_db2.txt\n"); + return 1; + } + i=0; + while(fgets(line, sizeof(line)-1, fp)){ + if(line[0]=='/' && line[1]=='/') + continue; + for(j=0,p=line;j<MAX_LEVEL && p;j++){ + if(sscanf(p,"%d",&k)==0) + break; + job_bonus[0][i][j]=k; + job_bonus[2][i][j]=k; //—{ŽqE‚̃{?ƒiƒX‚Í•ª‚©‚ç‚È‚¢‚Ì‚Å? + p=strchr(p,','); + if(p) p++; + } + i++; +// -- moonsoul (below two lines added to accommodate high numbered new class ids) + if(i==24) + i=4001; + if(i==MAX_PC_CLASS) + break; + } + fclose(fp); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/job_db2.txt"); + ShowStatus(tmp_output); + + // JOBƒ{?ƒiƒX2 ?¶E—p + fp=fopen("db/job_db2-2.txt","r"); + if(fp==NULL){ + printf("can't read db/job_db2-2.txt\n"); + return 1; + } + i=0; + while(fgets(line, sizeof(line)-1, fp)){ + if(line[0]=='/' && line[1]=='/') + continue; + for(j=0,p=line;j<MAX_LEVEL && p;j++){ + if(sscanf(p,"%d",&k)==0) + break; + job_bonus[1][i][j]=k; + p=strchr(p,','); + if(p) p++; + } + i++; + if(i==MAX_PC_CLASS) + break; + } + fclose(fp); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/job_db2-2.txt"); + ShowStatus(tmp_output); + + // ƒTƒCƒY•ⳃe?ƒuƒ‹ + for(i=0;i<3;i++) + for(j=0;j<20;j++) + atkmods[i][j]=100; + fp=fopen("db/size_fix.txt","r"); + if(fp==NULL){ + printf("can't read db/size_fix.txt\n"); + return 1; + } + i=0; + while(fgets(line, sizeof(line)-1, fp)){ + char *split[20]; + if(line[0]=='/' && line[1]=='/') + continue; + if(atoi(line)<=0) + continue; + memset(split,0,sizeof(split)); + for(j=0,p=line;j<20 && p;j++){ + split[j]=p; + p=strchr(p,','); + if(p) *p++=0; + } + for(j=0;j<20 && split[j];j++) + atkmods[i][j]=atoi(split[j]); + i++; + } + fclose(fp); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/size_fix.txt"); + ShowStatus(tmp_output); + + // ¸?ƒf?ƒ^ƒe?ƒuƒ‹ + for(i=0;i<5;i++){ + for(j=0;j<10;j++) + percentrefinery[i][j]=100; + refinebonus[i][0]=0; + refinebonus[i][1]=0; + refinebonus[i][2]=10; + } + fp=fopen("db/refine_db.txt","r"); + if(fp==NULL){ + printf("can't read db/refine_db.txt\n"); + return 1; + } + i=0; + while(fgets(line, sizeof(line)-1, fp)){ + char *split[16]; + if(line[0]=='/' && line[1]=='/') + continue; + if(atoi(line)<=0) + continue; + memset(split,0,sizeof(split)); + for(j=0,p=line;j<16 && p;j++){ + split[j]=p; + p=strchr(p,','); + if(p) *p++=0; + } + refinebonus[i][0]=atoi(split[0]); // ¸?ƒ{?ƒiƒX + refinebonus[i][1]=atoi(split[1]); // ‰ß?¸?ƒ{?ƒiƒX + refinebonus[i][2]=atoi(split[2]); // ˆÀ‘S¸?ŒÀŠE + for(j=0;j<10 && split[j];j++) + percentrefinery[i][j]=atoi(split[j+3]); + i++; + } + fclose(fp); //Lupus. close this file!!! + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/refine_db.txt"); + ShowStatus(tmp_output); + + return 0; +} + +/*========================================== + * ƒXƒLƒ‹ŠÖŒW‰Šú‰»ˆ— + *------------------------------------------ + */ +int do_init_status(void) +{ + add_timer_func_list(status_change_timer,"status_change_timer"); + status_readdb(); + status_calc_sigma(); + return 0; +} diff --git a/src/map/status.h b/src/map/status.h new file mode 100644 index 000000000..a07c47153 --- /dev/null +++ b/src/map/status.h @@ -0,0 +1,271 @@ +#ifndef _STATUS_H_ +#define _STATUS_H_ + +enum { // struct map_session_data ‚Ì status_change‚Ì”Ô?ƒe?ƒuƒ‹ +// SC_SENDMAX–¢?‚̓Nƒ‰ƒCƒAƒ“ƒg‚Ö‚Ì’Ê’m‚ ‚èB +// 2-2ŽŸE‚Ì’l‚͂Ȃñ‚©‚ß‚¿‚á‚‚¿‚á‚Á‚Û‚¢‚̂Ŏb’èB‚½‚Ô‚ñ?X‚³‚ê‚Ü‚·B + SC_SENDMAX = 128, // note: max is now 182, but we'll need to do alot of moving around + SC_PROVOKE = 0, + SC_ENDURE = 1, + SC_TWOHANDQUICKEN = 2, + SC_CONCENTRATE = 3, + SC_HIDING = 4, + SC_CLOAKING = 5, + SC_ENCPOISON = 6, + SC_POISONREACT = 7, + SC_QUAGMIRE = 8, + SC_ANGELUS = 9, + SC_BLESSING = 10, + SC_SIGNUMCRUCIS = 11, + SC_INCREASEAGI = 12, + SC_DECREASEAGI = 13, + SC_SLOWPOISON = 14, + SC_IMPOSITIO = 15, + SC_SUFFRAGIUM = 16, + SC_ASPERSIO = 17, + SC_BENEDICTIO = 18, + SC_KYRIE = 19, + SC_MAGNIFICAT = 20, + SC_GLORIA = 21, + SC_AETERNA = 22, + SC_ADRENALINE = 23, + SC_WEAPONPERFECTION = 24, + SC_OVERTHRUST = 25, + SC_MAXIMIZEPOWER = 26, + SC_RIDING = 27, + SC_FALCON = 28, + SC_TRICKDEAD = 29, + SC_LOUD = 30, + SC_ENERGYCOAT = 31, + SC_BROKNARMOR = 32, + SC_BROKNWEAPON = 33, + SC_HALLUCINATION = 34, + SC_WEIGHT50 = 35, + SC_WEIGHT90 = 36, + SC_SPEEDPOTION0 = 37, + SC_SPEEDPOTION1 = 38, + SC_SPEEDPOTION2 = 39, + SC_SPEEDPOTION3 = 40, + SC_SPEEDUP0 = 41, // for skill speedup + SC_SPEEDUP1 = 42, // for skill speedup +//-- 43-50 + SC_STRIPWEAPON = 50, + SC_STRIPSHIELD = 51, + SC_STRIPARMOR = 52, + SC_STRIPHELM = 53, + SC_CP_WEAPON = 54, + SC_CP_SHIELD = 55, + SC_CP_ARMOR = 56, + SC_CP_HELM = 57, + SC_AUTOGUARD = 58, + SC_REFLECTSHIELD = 59, + SC_DEVOTION = 60, + SC_PROVIDENCE = 61, + SC_DEFENDER = 62, + SC_AUTOSPELL = 65, + SC_SPEARSQUICKEN = 68, +//-- 69-85 + SC_EXPLOSIONSPIRITS = 86, + SC_STEELBODY = 87, + SC_COMBO = 89, + SC_FLAMELAUNCHER = 90, + SC_FROSTWEAPON = 91, + SC_LIGHTNINGLOADER = 92, + SC_SEISMICWEAPON = 93, +//-- 94-102 + SC_AURABLADE = 103, /* ƒI?ƒ‰ƒuƒŒ?ƒh */ + SC_PARRYING = 104, /* ƒpƒŠƒCƒ“ƒO */ + SC_CONCENTRATION = 105, /* ƒRƒ“ƒZƒ“ƒgƒŒ?ƒVƒ‡ƒ“ */ + SC_TENSIONRELAX = 106, /* ƒeƒ“ƒVƒ‡ƒ“ƒŠƒ‰ƒbƒNƒX */ + SC_BERSERK = 107, /* ƒo?ƒT?ƒN */ +//-- 108, 109 + SC_ASSUMPTIO = 110, /* ƒAƒVƒƒƒ“ƒvƒeƒBƒI */ +//-- 111, 112 + SC_MAGICPOWER = 113, /* –‚–@—Í?• */ + SC_EDP = 114, /* ƒGƒtƒFƒNƒg‚ª”»–¾‚µ‚½‚çˆÚ“® */ + SC_TRUESIGHT = 115, /* ƒgƒDƒ‹?ƒTƒCƒg */ + SC_WINDWALK = 116, /* ƒEƒCƒ“ƒhƒEƒH?ƒN */ + SC_MELTDOWN = 117, /* ƒƒ‹ƒgƒ_ƒEƒ“ */ + SC_CARTBOOST = 118, /* ƒJ?ƒgƒu?ƒXƒg */ +//-- 119 + SC_REJECTSWORD = 120, /* ƒŠƒWƒFƒNƒgƒ\?ƒh */ + SC_MARIONETTE = 121, /* ƒ}ƒŠƒIƒlƒbƒgƒRƒ“ƒgƒ?ƒ‹ */ + SC_MARIONETTE2 = 122, // Marionette target +//-- 123 + SC_BLEEDING = 124, /* ƒwƒbƒhƒNƒ‰ƒbƒVƒ… */ + SC_JOINTBEAT = 125, /* ƒWƒ‡ƒCƒ“ƒgƒr?ƒg */ +//-- 126, 127 + + SC_STONE = 128, + SC_FREEZE = 129, +// <-- 130 = a baby skill status? + SC_STAN = 130, + SC_SLEEP = 131, +// <-- 132 = another baby skill? + SC_POISON = 132, + SC_CURSE = 133, + SC_SILENCE = 134, + SC_CONFUSION = 135, + SC_BLIND = 136, + SC_DIVINA = SC_SILENCE, +//-- 137-139 + SC_SAFETYWALL = 140, + SC_PNEUMA = 141, +//-- 142 + SC_ANKLE = 143, + SC_DANCING = 144, + SC_KEEPING = 145, + SC_BARRIER = 146, +//-- 147,148 + SC_MAGICROD = 149, + SC_SIGHT = 150, + SC_RUWACH = 151, + SC_AUTOCOUNTER = 152, + SC_VOLCANO = 153, + SC_DELUGE = 154, + SC_VIOLENTGALE = 155, + SC_BLADESTOP_WAIT = 156, + SC_BLADESTOP = 157, + SC_EXTREMITYFIST = 158, +//-- 159 + SC_LULLABY =160, + SC_RICHMANKIM =161, + SC_ETERNALCHAOS =162, + SC_DRUMBATTLE =163, + SC_NIBELUNGEN =164, + SC_ROKISWEIL =165, + SC_INTOABYSS =166, + SC_SIEGFRIED =167, + SC_DISSONANCE =168, + SC_WHISTLE =169, + SC_ASSNCROS =170, + SC_POEMBRAGI =171, + SC_APPLEIDUN =172, + SC_UGLYDANCE =173, + SC_HUMMING =174, + SC_DONTFORGETME =175, + SC_FORTUNE =176, + SC_SERVICE4U =177, + SC_SPIDERWEB =180, /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */ +// <-- 181 = unknown status +// <-- 182 = unknown status + SC_SACRIFICE =184, /* ƒTƒNƒŠƒtƒ@ƒCƒX */ + SC_WEDDING =187, //Œ‹¥—p(Œ‹¥ˆßւɂȂÁ‚Ä?‚‚Ì‚ª?‚¢‚Æ‚©) + SC_NOCHAT =188, //ÔƒGƒ‚?‘Ô + SC_SPLASHER =189, /* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ? */ + SC_SELFDESTRUCTION =190, /* Ž©”š */ + SC_MEMORIZE =197, /* ƒƒ‚ƒ‰ƒCƒY */ // changed from 181 to 192 + SC_DPOISON =198, /* –Ò“Å */ + +// Used by English Team + SC_SLOWDOWN =45, // for skill slowdown + SC_AUTOBERSERK =46, + SC_SIGHTTRASHER =73, + SC_BASILICA =102, // temporarily use this before an actual id is found [celest] + + SC_ENSEMBLE =159, + SC_FOGWALL =178, + SC_GOSPEL =179, + SC_PRESERVE =181, + SC_BATTLEORDERS =182, + SC_MOONLIT =183, + SC_ATKPOT =185, // [Valaris] + SC_MATKPOT =186, // [Valaris] + SC_MINDBREAKER =191, + SC_SPELLBREAKER =192, + SC_LANDPROTECTOR =193, + SC_ADAPTATION =194, + SC_CHASEWALK =195, + SC_REGENERATION =196, + SC_GUILDAURA =199, + SC_BABY =200, + +// Icons + _SC_BABY =200 +}; +extern int SkillStatusChangeTable[]; + +extern int current_equip_item_index; + +// ƒpƒ‰ƒ[ƒ^Š“¾Œn battle.c ‚æ‚èˆÚ“® +int status_get_class(struct block_list *bl); +int status_get_dir(struct block_list *bl); +int status_get_lv(struct block_list *bl); +int status_get_range(struct block_list *bl); +int status_get_hp(struct block_list *bl); +int status_get_max_hp(struct block_list *bl); +int status_get_str(struct block_list *bl); +int status_get_agi(struct block_list *bl); +int status_get_vit(struct block_list *bl); +int status_get_int(struct block_list *bl); +int status_get_dex(struct block_list *bl); +int status_get_luk(struct block_list *bl); +int status_get_hit(struct block_list *bl); +int status_get_flee(struct block_list *bl); +int status_get_def(struct block_list *bl); +int status_get_mdef(struct block_list *bl); +int status_get_flee2(struct block_list *bl); +int status_get_def2(struct block_list *bl); +int status_get_mdef2(struct block_list *bl); +int status_get_baseatk(struct block_list *bl); +int status_get_atk(struct block_list *bl); +int status_get_atk2(struct block_list *bl); +int status_get_speed(struct block_list *bl); +int status_get_adelay(struct block_list *bl); +int status_get_amotion(struct block_list *bl); +int status_get_dmotion(struct block_list *bl); +int status_get_element(struct block_list *bl); +int status_get_attack_element(struct block_list *bl); +int status_get_attack_element2(struct block_list *bl); //¶Žè•Ší‘®«Žæ“¾ +#define status_get_elem_type(bl) (status_get_element(bl)%10) +#define status_get_elem_level(bl) (status_get_element(bl)/10/2) +int status_get_party_id(struct block_list *bl); +int status_get_guild_id(struct block_list *bl); +int status_get_race(struct block_list *bl); +int status_get_size(struct block_list *bl); +int status_get_mode(struct block_list *bl); +int status_get_mexp(struct block_list *bl); +int status_get_race2(struct block_list *bl); + +struct status_change *status_get_sc_data(struct block_list *bl); +short *status_get_sc_count(struct block_list *bl); +short *status_get_opt1(struct block_list *bl); +short *status_get_opt2(struct block_list *bl); +short *status_get_opt3(struct block_list *bl); +short *status_get_option(struct block_list *bl); + +int status_get_matk1(struct block_list *bl); +int status_get_matk2(struct block_list *bl); +int status_get_critical(struct block_list *bl); +int status_get_atk_(struct block_list *bl); +int status_get_atk_2(struct block_list *bl); +int status_get_atk2(struct block_list *bl); + +int status_isdead(struct block_list *bl); + +int status_get_sc_def(struct block_list *bl, int type); +#define status_get_sc_def_mdef(bl) (status_get_sc_def(bl, SP_MDEF1)) +#define status_get_sc_def_vit(bl) (status_get_sc_def(bl, SP_DEF2)) +#define status_get_sc_def_int(bl) (status_get_sc_def(bl, SP_MDEF2)) +#define status_get_sc_def_luk(bl) (status_get_sc_def(bl, SP_LUK)) + +// ó‘ÔˆÙíŠÖ˜A skill.c ‚æ‚èˆÚ“® +int status_change_start(struct block_list *bl,int type,int val1,int val2,int val3,int val4,int tick,int flag); +int status_change_end( struct block_list* bl , int type,int tid ); +int status_change_timer(int tid, unsigned int tick, int id, int data); +int status_change_timer_sub(struct block_list *bl, va_list ap ); +int status_change_clear(struct block_list *bl,int type); + +// ƒXƒe[ƒ^ƒXŒvŽZ pc.c ‚©‚番—£ +// pc_calcstatus +int status_calc_pc(struct map_session_data* sd,int first); +int status_calc_speed(struct map_session_data*); // [Celest] +// int status_calc_skilltree(struct map_session_data *sd); +int status_getrefinebonus(int lv,int type); +int status_percentrefinery(struct map_session_data *sd,struct item *item); +extern int percentrefinery[5][10]; + +int status_readdb(void); +int do_init_status(void); + +#endif diff --git a/src/map/storage.c b/src/map/storage.c index fc6f63cdd..82ecd9321 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -3,14 +3,18 @@ #include <stdlib.h> #include <string.h> -#include "db.h" +#include "../common/db.h" +#include "../common/nullpo.h" +#include "../common/malloc.h" + #include "itemdb.h" #include "clif.h" #include "intif.h" #include "pc.h" #include "storage.h" #include "guild.h" -#include "nullpo.h" +#include "battle.h" +#include "atcommand.h" #ifdef MEMWATCH #include "memwatch.h" @@ -42,13 +46,13 @@ struct item *i2=(struct item *)_i2; void sortage_sortitem(struct storage* stor){ nullpo_retv(stor); - qsort(stor->storage, MAX_STORAGE, sizeof(struct item), storage_comp_item); + qsort(stor->storage_, MAX_STORAGE, sizeof(struct item), storage_comp_item); } void sortage_gsortitem(struct guild_storage* gstor){ nullpo_retv(gstor); - qsort(gstor->storage, MAX_GUILD_STORAGE, sizeof(struct item), storage_comp_item); + qsort(gstor->storage_, MAX_GUILD_STORAGE, sizeof(struct item), storage_comp_item); } /*========================================== @@ -61,17 +65,32 @@ int do_init_storage(void) // map.c::do_init()‚©‚çŒÄ‚΂ê‚é guild_storage_db=numdb_init(); return 1; } - -void do_final_storage(void) // map.c::do_final()‚©‚çŒÄ‚΂ê‚é +static int guild_storage_db_final(void *key,void *data,va_list ap) +{ + struct guild_storage *gstor=(struct guild_storage *) data; + aFree(gstor); + return 0; +} +static int storage_db_final(void *key,void *data,va_list ap) { + struct storage *stor=(struct storage *) data; + aFree(stor); + return 0; +} +void do_final_storage(void) // by [MC Cameri] +{ + if (storage_db) + numdb_final(storage_db,storage_db_final); + if (guild_storage_db) + numdb_final(guild_storage_db,guild_storage_db_final); } struct storage *account2storage(int account_id) { struct storage *stor; - stor=numdb_search(storage_db,account_id); + stor=(struct storage *) numdb_search(storage_db,account_id); if(stor == NULL) { - stor = calloc(sizeof(struct storage), 1); + stor = (struct storage *) aCallocA(sizeof(struct storage), 1); if(stor == NULL){ printf("storage: out of memory!\n"); exit(0); @@ -85,15 +104,15 @@ struct storage *account2storage(int account_id) // Just to ask storage, without creation struct storage *account2storage2(int account_id) { - return numdb_search(storage_db, account_id); + return (struct storage *) numdb_search(storage_db, account_id); } int storage_delete(int account_id) { - struct storage *stor = numdb_search(storage_db,account_id); + struct storage *stor = (struct storage *) numdb_search(storage_db,account_id); if(stor) { numdb_erase(storage_db,account_id); - free(stor); + aFree(stor); } return 0; } @@ -108,38 +127,25 @@ int storage_storageopen(struct map_session_data *sd) nullpo_retr(0, sd); - if((stor = numdb_search(storage_db,sd->status.account_id)) != NULL) { - stor->storage_status = 1; - sd->state.storage_flag = 0; - clif_storageitemlist(sd,stor); - clif_storageequiplist(sd,stor); - clif_updatestorageamount(sd,stor); - return 0; + if(pc_isGM(sd) && pc_isGM(sd) < battle_config.gm_can_drop_lv) { + clif_displaymessage(sd->fd, msg_txt(246)); + return 1; + } + if((stor = (struct storage *) numdb_search(storage_db,sd->status.account_id)) != NULL) { + if (stor->storage_status == 0) { + stor->storage_status = 1; + sd->state.storage_flag = 0; + clif_storageitemlist(sd,stor); + clif_storageequiplist(sd,stor); + clif_updatestorageamount(sd,stor); + return 0; + } } else intif_request_storage(sd->status.account_id); return 1; } -int storage_storageopen2(struct map_session_data *sd, struct map_session_data *pl_sd) -{ - struct storage *stor; - if(sd == NULL || pl_sd == NULL) - { - printf("storage_storageopen nullpo\n"); - return 0; - } - - if((stor = numdb_search(storage_db,pl_sd->status.account_id)) != NULL) - { - clif_storageitemlist(sd,stor); - clif_storageequiplist(sd,stor); - clif_updatestorageamount(sd,stor); - return 1; - } - return 0; -} - /*========================================== * ƒJƒvƒ‰‘qŒÉ‚ÖƒAƒCƒeƒ€’ljÁ *------------------------------------------ @@ -153,6 +159,8 @@ int storage_additem(struct map_session_data *sd,struct storage *stor,struct item nullpo_retr(1, stor); nullpo_retr(1, item_data); + stor->dirty = 1; + if(item_data->nameid <= 0 || amount <= 0) return 1; nullpo_retr(1, data = itemdb_search(item_data->nameid)); @@ -161,12 +169,10 @@ int storage_additem(struct map_session_data *sd,struct storage *stor,struct item if(!itemdb_isequip2(data)){ // ‘•”õ•i‚ł͂Ȃ¢‚Ì‚ÅAŠùŠ—L•i‚È‚çŒÂ”‚̂ݕω»‚³‚¹‚é for(i=0;i<MAX_STORAGE;i++){ - if(stor->storage[i].nameid == item_data->nameid && - stor->storage[i].card[0] == item_data->card[0] && stor->storage[i].card[1] == item_data->card[1] && - stor->storage[i].card[2] == item_data->card[2] && stor->storage[i].card[3] == item_data->card[3]){ - if(stor->storage[i].amount+amount > MAX_AMOUNT) + if( compare_item (&stor->storage_[i], item_data)) { + if(stor->storage_[i].amount+amount > MAX_AMOUNT) return 1; - stor->storage[i].amount+=amount; + stor->storage_[i].amount+=amount; clif_storageitemadded(sd,stor,i,amount); break; } @@ -175,9 +181,9 @@ int storage_additem(struct map_session_data *sd,struct storage *stor,struct item if(i>=MAX_STORAGE){ // ‘•”õ•i‚©–¢Š—L•i‚¾‚Á‚½‚̂ŋ󂫗“‚֒ljÁ for(i=0;i<MAX_STORAGE;i++){ - if(stor->storage[i].nameid==0){ - memcpy(&stor->storage[i],item_data,sizeof(stor->storage[0])); - stor->storage[i].amount=amount; + if(stor->storage_[i].nameid==0){ + memcpy(&stor->storage_[i],item_data,sizeof(stor->storage_[0])); + stor->storage_[i].amount=amount; stor->storage_amount++; clif_storageitemadded(sd,stor,i,amount); clif_updatestorageamount(sd,stor); @@ -187,6 +193,7 @@ int storage_additem(struct map_session_data *sd,struct storage *stor,struct item if(i>=MAX_STORAGE) return 1; } + return 0; } /*========================================== @@ -198,17 +205,19 @@ int storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int a nullpo_retr(1, sd); nullpo_retr(1, stor); - if(stor->storage[n].nameid==0 || stor->storage[n].amount<amount) + if(stor->storage_[n].nameid==0 || stor->storage_[n].amount<amount) return 1; - stor->storage[n].amount-=amount; - if(stor->storage[n].amount==0){ - memset(&stor->storage[n],0,sizeof(stor->storage[0])); + stor->storage_[n].amount-=amount; + if(stor->storage_[n].amount==0){ + memset(&stor->storage_[n],0,sizeof(stor->storage_[0])); stor->storage_amount--; clif_updatestorageamount(sd,stor); } clif_storageitemremoved(sd,n,amount); + stor->dirty = 1; + return 0; } /*========================================== @@ -220,15 +229,16 @@ int storage_storageadd(struct map_session_data *sd,int index,int amount) struct storage *stor; nullpo_retr(0, sd); - nullpo_retr(0, stor=account2storage(sd->status.account_id)); + nullpo_retr(0, stor=account2storage2(sd->status.account_id)); if( (stor->storage_amount <= MAX_STORAGE) && (stor->storage_status == 1) ) { // storage not full & storage open if(index>=0 && index<MAX_INVENTORY) { // valid index - if( (amount <= sd->status.inventory[index].amount) && (amount > 0) ) { //valid amount - if(storage_additem(sd,stor,&sd->status.inventory[index],amount)==0) - // remove item from inventory - pc_delitem(sd,index,amount,0); - } // valid amount + if( (amount <= sd->status.inventory[index].amount) && (amount > 0) ) { //valid amount +// log_tostorage(sd, index, 0); + if(storage_additem(sd,stor,&sd->status.inventory[index],amount)==0) + // remove item from inventory + pc_delitem(sd,index,amount,0); + } // valid amount }// valid index }// storage not full & storage open @@ -245,15 +255,16 @@ int storage_storageget(struct map_session_data *sd,int index,int amount) int flag; nullpo_retr(0, sd); - nullpo_retr(0, stor=account2storage(sd->status.account_id)); + nullpo_retr(0, stor=account2storage2(sd->status.account_id)); if(stor->storage_status == 1) { // storage open if(index>=0 && index<MAX_STORAGE) { // valid index - if( (amount <= stor->storage[index].amount) && (amount > 0) ) { //valid amount - if((flag = pc_additem(sd,&stor->storage[index],amount)) == 0) + if( (amount <= stor->storage_[index].amount) && (amount > 0) ) { //valid amount + if((flag = pc_additem(sd,&stor->storage_[index],amount)) == 0) storage_delitem(sd,stor,index,amount); else clif_additem(sd,0,0,flag); +// log_fromstorage(sd, index, 0); } // valid amount }// valid index }// storage open @@ -269,7 +280,7 @@ int storage_storageaddfromcart(struct map_session_data *sd,int index,int amount) struct storage *stor; nullpo_retr(0, sd); - nullpo_retr(0, stor=account2storage(sd->status.account_id)); + nullpo_retr(0, stor=account2storage2(sd->status.account_id)); if( (stor->storage_amount <= MAX_STORAGE) && (stor->storage_status == 1) ) { // storage not full & storage open if(index>=0 && index<MAX_INVENTORY) { // valid index @@ -292,12 +303,12 @@ int storage_storagegettocart(struct map_session_data *sd,int index,int amount) struct storage *stor; nullpo_retr(0, sd); - nullpo_retr(0, stor=account2storage(sd->status.account_id)); + nullpo_retr(0, stor=account2storage2(sd->status.account_id)); if(stor->storage_status == 1) { // storage open if(index>=0 && index<MAX_STORAGE) { // valid index - if( (amount <= stor->storage[index].amount) && (amount > 0) ) { //valid amount - if(pc_cart_additem(sd,&stor->storage[index],amount)==0){ + if( (amount <= stor->storage_[index].amount) && (amount > 0) ) { //valid amount + if(pc_cart_additem(sd,&stor->storage_[index],amount)==0){ storage_delitem(sd,stor,index,amount); } } // valid amount @@ -317,12 +328,14 @@ int storage_storageclose(struct map_session_data *sd) struct storage *stor; nullpo_retr(0, sd); - nullpo_retr(0, stor=account2storage(sd->status.account_id)); + nullpo_retr(0, stor=account2storage2(sd->status.account_id)); stor->storage_status=0; sd->state.storage_flag = 0; clif_storageclose(sd); + storage_storage_save(sd); + sortage_sortitem(stor); return 0; } @@ -337,20 +350,36 @@ int storage_storage_quit(struct map_session_data *sd) nullpo_retr(0, sd); - stor = numdb_search(storage_db,sd->status.account_id); - if(stor) stor->storage_status = 0; + stor = (struct storage *) numdb_search(storage_db,sd->status.account_id); + if(stor) { + stor->storage_status = 0; + storage_storage_save(sd); + } return 0; } +void storage_storage_dirty(struct map_session_data *sd) +{ + struct storage *stor; + + stor=(struct storage *) numdb_search(storage_db,sd->status.account_id); + + if(stor) + stor->dirty = 1; +} + int storage_storage_save(struct map_session_data *sd) { struct storage *stor; nullpo_retr(0, sd); - stor=numdb_search(storage_db,sd->status.account_id); - if(stor) intif_send_storage(stor); + stor=(struct storage *) numdb_search(storage_db,sd->status.account_id); + if(stor && stor->dirty) { + intif_send_storage(stor); + stor->dirty = 0; + } return 0; } @@ -359,9 +388,9 @@ struct guild_storage *guild2storage(int guild_id) { struct guild_storage *gs = NULL; if(guild_search(guild_id) != NULL) { - gs=numdb_search(guild_storage_db,guild_id); + gs=(struct guild_storage *) numdb_search(guild_storage_db,guild_id); if(gs == NULL) { - gs = calloc(sizeof(struct guild_storage), 1); + gs = (struct guild_storage *) aCallocA(sizeof(struct guild_storage), 1); if(gs==NULL){ printf("storage: out of memory!\n"); exit(0); @@ -375,10 +404,10 @@ struct guild_storage *guild2storage(int guild_id) int guild_storage_delete(int guild_id) { - struct guild_storage *gstor = numdb_search(guild_storage_db,guild_id); + struct guild_storage *gstor = (struct guild_storage *) numdb_search(guild_storage_db,guild_id); if(gstor) { numdb_erase(guild_storage_db,guild_id); - free(gstor); + aFree(gstor); } return 0; } @@ -391,7 +420,7 @@ int storage_guild_storageopen(struct map_session_data *sd) if(sd->status.guild_id <= 0) return 2; - if((gstor = numdb_search(guild_storage_db,sd->status.guild_id)) != NULL) { + if((gstor = (struct guild_storage *) numdb_search(guild_storage_db,sd->status.guild_id)) != NULL) { if(gstor->storage_status) return 1; gstor->storage_status = 1; @@ -427,12 +456,10 @@ int guild_storage_additem(struct map_session_data *sd,struct guild_storage *stor if(!itemdb_isequip2(data)){ // ‘•”õ•i‚ł͂Ȃ¢‚Ì‚ÅAŠùŠ—L•i‚È‚çŒÂ”‚̂ݕω»‚³‚¹‚é for(i=0;i<MAX_GUILD_STORAGE;i++){ - if(stor->storage[i].nameid == item_data->nameid && - stor->storage[i].card[0] == item_data->card[0] && stor->storage[i].card[1] == item_data->card[1] && - stor->storage[i].card[2] == item_data->card[2] && stor->storage[i].card[3] == item_data->card[3]){ - if(stor->storage[i].amount+amount > MAX_AMOUNT) + if(compare_item(&stor->storage_[i], item_data)) { + if(stor->storage_[i].amount+amount > MAX_AMOUNT) return 1; - stor->storage[i].amount+=amount; + stor->storage_[i].amount+=amount; clif_guildstorageitemadded(sd,stor,i,amount); break; } @@ -441,9 +468,9 @@ int guild_storage_additem(struct map_session_data *sd,struct guild_storage *stor if(i>=MAX_GUILD_STORAGE){ // ‘•”õ•i‚©–¢Š—L•i‚¾‚Á‚½‚̂ŋ󂫗“‚֒ljÁ for(i=0;i<MAX_GUILD_STORAGE;i++){ - if(stor->storage[i].nameid==0){ - memcpy(&stor->storage[i],item_data,sizeof(stor->storage[0])); - stor->storage[i].amount=amount; + if(stor->storage_[i].nameid==0){ + memcpy(&stor->storage_[i],item_data,sizeof(stor->storage_[0])); + stor->storage_[i].amount=amount; stor->storage_amount++; clif_guildstorageitemadded(sd,stor,i,amount); clif_updateguildstorageamount(sd,stor); @@ -461,12 +488,12 @@ int guild_storage_delitem(struct map_session_data *sd,struct guild_storage *stor nullpo_retr(1, sd); nullpo_retr(1, stor); - if(stor->storage[n].nameid==0 || stor->storage[n].amount<amount) + if(stor->storage_[n].nameid==0 || stor->storage_[n].amount<amount) return 1; - stor->storage[n].amount-=amount; - if(stor->storage[n].amount==0){ - memset(&stor->storage[n],0,sizeof(stor->storage[0])); + stor->storage_[n].amount-=amount; + if(stor->storage_[n].amount==0){ + memset(&stor->storage_[n],0,sizeof(stor->storage_[0])); stor->storage_amount--; clif_updateguildstorageamount(sd,stor); } @@ -485,6 +512,7 @@ int storage_guild_storageadd(struct map_session_data *sd,int index,int amount) if( (stor->storage_amount <= MAX_GUILD_STORAGE) && (stor->storage_status == 1) ) { // storage not full & storage open if(index>=0 && index<MAX_INVENTORY) { // valid index if( (amount <= sd->status.inventory[index].amount) && (amount > 0) ) { //valid amount +// log_tostorage(sd, index, 1); if(guild_storage_additem(sd,stor,&sd->status.inventory[index],amount)==0) // remove item from inventory pc_delitem(sd,index,amount,0); @@ -506,11 +534,12 @@ int storage_guild_storageget(struct map_session_data *sd,int index,int amount) if((stor=guild2storage(sd->status.guild_id)) != NULL) { if(stor->storage_status == 1) { // storage open if(index>=0 && index<MAX_GUILD_STORAGE) { // valid index - if( (amount <= stor->storage[index].amount) && (amount > 0) ) { //valid amount - if((flag = pc_additem(sd,&stor->storage[index],amount)) == 0) + if( (amount <= stor->storage_[index].amount) && (amount > 0) ) { //valid amount + if((flag = pc_additem(sd,&stor->storage_[index],amount)) == 0) guild_storage_delitem(sd,stor,index,amount); else clif_additem(sd,0,0,flag); +// log_fromstorage(sd, index, 1); } // valid amount }// valid index }// storage open @@ -548,8 +577,8 @@ int storage_guild_storagegettocart(struct map_session_data *sd,int index,int amo if((stor=guild2storage(sd->status.guild_id)) != NULL) { if(stor->storage_status == 1) { // storage open if(index>=0 && index<MAX_GUILD_STORAGE) { // valid index - if( (amount <= stor->storage[index].amount) && (amount > 0) ) { //valid amount - if(pc_cart_additem(sd,&stor->storage[index],amount)==0){ + if( (amount <= stor->storage_[index].amount) && (amount > 0) ) { //valid amount + if(pc_cart_additem(sd,&stor->storage_[index],amount)==0){ guild_storage_delitem(sd,stor,index,amount); } } // valid amount @@ -583,7 +612,7 @@ int storage_guild_storage_quit(struct map_session_data *sd,int flag) nullpo_retr(0, sd); - stor = numdb_search(guild_storage_db,sd->status.guild_id); + stor = (struct guild_storage *) numdb_search(guild_storage_db,sd->status.guild_id); if(stor) { if(!flag) intif_send_guild_storage(sd->status.account_id,stor); diff --git a/src/map/storage.h b/src/map/storage.h index 352dee4f0..7b2ac2cbe 100644 --- a/src/map/storage.h +++ b/src/map/storage.h @@ -5,7 +5,6 @@ #include "mmo.h" int storage_storageopen(struct map_session_data *sd); -int storage_storageopen2(struct map_session_data *sd,struct map_session_data *pl_sd); int storage_storageadd(struct map_session_data *sd,int index,int amount); int storage_storageget(struct map_session_data *sd,int index,int amount); int storage_storageaddfromcart(struct map_session_data *sd,int index,int amount); @@ -18,6 +17,7 @@ struct storage *account2storage2(int account_id); int storage_delete(int account_id); int storage_storage_quit(struct map_session_data *sd); int storage_storage_save(struct map_session_data *sd); +void storage_storage_dirty(struct map_session_data *sd); struct guild_storage *guild2storage(int guild_id); int guild_storage_delete(int guild_id); diff --git a/src/map/trade.c b/src/map/trade.c index 9d2128690..eb1d45ba2 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -1,6 +1,10 @@ +// $Id: trade.c 375 2005-03-04 21:33:31Z Yor $ +//#include <config.h> + #include <stdio.h> #include <string.h> +#include "../common/nullpo.h" #include "clif.h" #include "itemdb.h" #include "map.h" @@ -8,44 +12,46 @@ #include "pc.h" #include "npc.h" #include "battle.h" -#include "nullpo.h" +#include "chrif.h" +#include "storage.h" +#include "intif.h" +#include "atcommand.h" #include "log.h" /*========================================== * Žæˆø—v¿‚𑊎è‚É‘—‚é *------------------------------------------ */ -void trade_traderequest(struct map_session_data *sd,int target_id) -{ +void trade_traderequest(struct map_session_data *sd, int target_id) { struct map_session_data *target_sd; nullpo_retv(sd); - if((target_sd = map_id2sd(target_id)) != NULL){ - if(!battle_config.invite_request_check) { - if(target_sd->guild_invite>0 || target_sd->party_invite>0){ - clif_tradestart(sd,2); // ‘ŠŽè‚ÍPT—v¿’†‚©Guild—v¿’† + if ((target_sd = map_id2sd(target_id)) != NULL) { + if (!battle_config.invite_request_check) { + if (target_sd->guild_invite > 0 || target_sd->party_invite > 0) { + clif_tradestart(sd, 2); // ‘ŠŽè‚ÍPT—v¿’†‚©Guild—v¿’† return; } } - if((target_sd->trade_partner !=0) || (sd->trade_partner !=0)) { - trade_tradecancel(sd); //person is in another trade - } - else{ - if((pc_isGM(sd) < 60) && (sd->bl.m != target_sd->bl.m - || (sd->bl.x - target_sd->bl.x <= -5 || sd->bl.x - target_sd->bl.x >= 5) - || (sd->bl.y - target_sd->bl.y <= -5 || sd->bl.y - target_sd->bl.y >= 5))) { - clif_tradestart(sd,0); //too far - } - else if(sd!=target_sd) { + if(pc_isGM(sd) && pc_isGM(target_sd) < battle_config.gm_can_drop_lv) { + clif_displaymessage(sd->fd, msg_txt(246)); + trade_tradecancel(sd); // GM is not allowed to trade + } else if ((target_sd->trade_partner != 0) || (sd->trade_partner != 0)) { + trade_tradecancel(sd); // person is in another trade + } else { + if (!pc_isGM(sd) && (sd->bl.m != target_sd->bl.m || + (sd->bl.x - target_sd->bl.x <= -5 || sd->bl.x - target_sd->bl.x >= 5) || + (sd->bl.y - target_sd->bl.y <= -5 || sd->bl.y - target_sd->bl.y >= 5))) { + clif_tradestart(sd, 0); // too far + } else if (sd != target_sd) { target_sd->trade_partner = sd->status.account_id; sd->trade_partner = target_sd->status.account_id; - clif_traderequest(target_sd,sd->status.name); + clif_traderequest(target_sd, sd->status.name); } } - } - else{ - clif_tradestart(sd,1); //character does not exist + } else { + clif_tradestart(sd, 1); // character does not exist } } @@ -53,34 +59,103 @@ void trade_traderequest(struct map_session_data *sd,int target_id) * Žæˆø—v¿ *------------------------------------------ */ -void trade_tradeack(struct map_session_data *sd,int type) -{ +void trade_tradeack(struct map_session_data *sd, int type) { struct map_session_data *target_sd; - + struct storage *stor; nullpo_retv(sd); - if((target_sd = map_id2sd(sd->trade_partner)) != NULL){ - clif_tradestart(target_sd,type); - clif_tradestart(sd,type); - if(type == 4){ // Cancel - sd->deal_locked =0; - sd->trade_partner=0; - target_sd->deal_locked=0; - target_sd->trade_partner=0; + if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) { + clif_tradestart(target_sd, type); + clif_tradestart(sd, type); + if (type == 4) { // Cancel + sd->deal_locked = 0; + sd->trade_partner = 0; + target_sd->deal_locked = 0; + target_sd->trade_partner = 0; } - if(sd->npc_id != 0) + if (sd->npc_id != 0) npc_event_dequeue(sd); - if(target_sd->npc_id != 0) + if (target_sd->npc_id != 0) npc_event_dequeue(target_sd); + + //close STORAGE window if it's open. It protects from spooffing packets [Lupus] + stor=account2storage2(sd->status.account_id); + if(stor!=NULL && stor->storage_status == 1) { + if (sd->state.storage_flag) //is it Guild Storage or Common + storage_guild_storageclose(sd); + else + storage_storageclose(sd); + }//END OF STORAGE CLOSE } } /*========================================== + * Check here hacker for duplicate item in trade + * normal client refuse to have 2 same types of item (except equipment) in same trade window + * normal client authorise only no equiped item and only from inventory + *------------------------------------------ + */ +int impossible_trade_check(struct map_session_data *sd) { + struct item inventory[MAX_INVENTORY]; + char message_to_gm[200]; + int i, index; + + nullpo_retr(0, sd); + + // get inventory of player + memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY); + +/* remove this part: arrows can be trade and equiped + // remove equiped items (they can not be trade) + for (i = 0; i < MAX_INVENTORY; i++) + if (inventory[i].nameid > 0 && inventory[i].equip) + memset(&inventory[i], 0, sizeof(struct item)); +*/ + + // check items in player inventory + for(i = 0; i < 10; i++) + if (sd->deal_item_amount[i] < 0) { // negativ? -> hack +// printf("Negativ amount in trade, by hack!\n"); // normal client send cancel when we type negativ amount + return -1; + } else if (sd->deal_item_amount[i] > 0) { + index = sd->deal_item_index[i] - 2; + inventory[index].amount -= sd->deal_item_amount[i]; // remove item from inventory +// printf("%d items left\n", inventory[index].amount); + if (inventory[index].amount < 0) { // if more than the player have -> hack +// printf("A player try to trade more items that he has: hack!\n"); + sprintf(message_to_gm, msg_txt(538), sd->status.name, sd->status.account_id); // Hack on trade: character '%s' (account: %d) try to trade more items that he has. + intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm); + sprintf(message_to_gm, msg_txt(539), sd->status.inventory[index].amount, sd->status.inventory[index].nameid, sd->status.inventory[index].amount - inventory[index].amount); // This player has %d of a kind of item (id: %d), and try to trade %d of them. + intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm); + // if we block people + if (battle_config.ban_hack_trade < 0) { + chrif_char_ask_name(-1, sd->status.name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block + clif_setwaitclose(sd->fd); // forced to disconnect because of the hack + // message about the ban + sprintf(message_to_gm, msg_txt(540), battle_config.ban_spoof_namer); // This player has been definitivly blocked. + // if we ban people + } else if (battle_config.ban_hack_trade > 0) { + chrif_char_ask_name(-1, sd->status.name, 2, 0, 0, 0, 0, battle_config.ban_hack_trade, 0); // type: 2 - ban (year, month, day, hour, minute, second) + clif_setwaitclose(sd->fd); // forced to disconnect because of the hack + // message about the ban + sprintf(message_to_gm, msg_txt(507), battle_config.ban_spoof_namer); // This player has been banned for %d minute(s). + } else { + // message about the ban + sprintf(message_to_gm, msg_txt(508)); // This player hasn't been banned (Ban option is disabled). + } + intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm); + return 1; + } + } + + return 0; +} + +/*========================================== * ƒAƒCƒeƒ€’ljÁ *------------------------------------------ */ -void trade_tradeadditem(struct map_session_data *sd, int index, int amount) -{ +void trade_tradeadditem(struct map_session_data *sd, int index, int amount) { struct map_session_data *target_sd; int trade_i; int trade_weight = 0; @@ -89,7 +164,7 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount) nullpo_retv(sd); if (((target_sd = map_id2sd(sd->trade_partner)) != NULL) && (sd->deal_locked < 1)){ - if (index < 2 || index >= MAX_INVENTORY + 2){ + if (index < 2 || index >= MAX_INVENTORY + 2) { if (index == 0) { if (amount > 0 && amount <= MAX_ZENY && amount <= sd->status.zeny && // check amount (target_sd->status.zeny + amount) <= MAX_ZENY) { // fix positiv overflow @@ -108,7 +183,7 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount) trade_weight += sd->inventory_data[index-2]->weight * amount; if (target_sd->weight + trade_weight > target_sd->max_weight){ clif_tradeitemok(sd, index, 1); // fail to add item -- the player was over weighted. - amount = 0; // [MouseJstr] + amount = 0; } else { for(c = 0; c == trade_i - 1; c++) { // re-deal exploit protection [Valaris] if (sd->deal_item_index[c] == index) { @@ -118,6 +193,10 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount) } sd->deal_item_index[trade_i] = index; sd->deal_item_amount[trade_i] += amount; + if (impossible_trade_check(sd)) { // check exploit (trade more items that you have) + trade_tradecancel(sd); + return; + } clif_tradeitemok(sd, index, 0); // success to add item clif_tradeadditem(sd, target_sd, index, amount); } @@ -134,27 +213,39 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount) * ƒAƒCƒeƒ€’ljÁŠ®—¹(ok‰Ÿ‚µ) *------------------------------------------ */ -void trade_tradeok(struct map_session_data *sd) -{ +void trade_tradeok(struct map_session_data *sd) { struct map_session_data *target_sd; int trade_i; nullpo_retv(sd); - - for(trade_i=0;trade_i<10;trade_i++) { - if(sd->deal_item_amount[trade_i]>sd->status.inventory[sd->deal_item_index[trade_i]-2].amount || - sd->deal_item_amount[trade_i]<0) { + + // check items + for(trade_i = 0; trade_i < 10; trade_i++) { + if ((((sd->deal_item_index[trade_i]-2) >= 0) && + (sd->deal_item_amount[trade_i] > sd->status.inventory[sd->deal_item_index[trade_i]-2].amount)) || + (sd->deal_item_amount[trade_i] < 0)) { trade_tradecancel(sd); return; } - } - - if((target_sd = map_id2sd(sd->trade_partner)) != NULL){ - sd->deal_locked=1; - clif_tradeitemok(sd,0,0); - clif_tradedeal_lock(sd,0); - clif_tradedeal_lock(target_sd,1); + + // check exploit (trade more items that you have) + if (impossible_trade_check(sd)) { + trade_tradecancel(sd); + return; + } + + // check zeny + if (sd->deal_zeny < 0 || sd->deal_zeny > MAX_ZENY || sd->deal_zeny > sd->status.zeny) { // check amount + trade_tradecancel(sd); + return; + } + + if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) { + sd->deal_locked = 1; + clif_tradeitemok(sd, 0, 0); + clif_tradedeal_lock(sd, 0); + clif_tradedeal_lock(target_sd, 1); } } @@ -162,38 +253,37 @@ void trade_tradeok(struct map_session_data *sd) * ŽæˆøƒLƒƒƒ“ƒZƒ‹ *------------------------------------------ */ -void trade_tradecancel(struct map_session_data *sd) -{ +void trade_tradecancel(struct map_session_data *sd) { struct map_session_data *target_sd; int trade_i; nullpo_retv(sd); - if((target_sd = map_id2sd(sd->trade_partner)) != NULL){ - for(trade_i=0; trade_i<10;trade_i++) { //give items back (only virtual) - if(sd->deal_item_amount[trade_i] != 0) { - clif_additem(sd,sd->deal_item_index[trade_i]-2,sd->deal_item_amount[trade_i],0); - sd->deal_item_index[trade_i] =0; - sd->deal_item_amount[trade_i]=0; + if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) { + for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual) + if (sd->deal_item_amount[trade_i] != 0) { + clif_additem(sd, sd->deal_item_index[trade_i] - 2, sd->deal_item_amount[trade_i], 0); + sd->deal_item_index[trade_i] = 0; + sd->deal_item_amount[trade_i] = 0; } - if(target_sd->deal_item_amount[trade_i] != 0) { - clif_additem(target_sd,target_sd->deal_item_index[trade_i]-2,target_sd->deal_item_amount[trade_i],0); - target_sd->deal_item_index[trade_i] =0; - target_sd->deal_item_amount[trade_i]=0; + if (target_sd->deal_item_amount[trade_i] != 0) { + clif_additem(target_sd, target_sd->deal_item_index[trade_i] - 2, target_sd->deal_item_amount[trade_i], 0); + target_sd->deal_item_index[trade_i] = 0; + target_sd->deal_item_amount[trade_i] = 0; } } - if(sd->deal_zeny) { - clif_updatestatus(sd,SP_ZENY); - sd->deal_zeny=0; + if (sd->deal_zeny) { + clif_updatestatus(sd, SP_ZENY); + sd->deal_zeny = 0; } - if(target_sd->deal_zeny) { - clif_updatestatus(target_sd,SP_ZENY); - target_sd->deal_zeny=0; + if (target_sd->deal_zeny) { + clif_updatestatus(target_sd, SP_ZENY); + target_sd->deal_zeny = 0; } - sd->deal_locked =0; - sd->trade_partner=0; - target_sd->deal_locked=0; - target_sd->trade_partner=0; + sd->deal_locked = 0; + sd->trade_partner = 0; + target_sd->deal_locked = 0; + target_sd->trade_partner = 0; clif_tradecancelled(sd); clif_tradecancelled(target_sd); } @@ -203,91 +293,96 @@ void trade_tradecancel(struct map_session_data *sd) * Žæˆø‹–‘ø(trade‰Ÿ‚µ) *------------------------------------------ */ -void trade_tradecommit(struct map_session_data *sd) -{ +void trade_tradecommit(struct map_session_data *sd) { struct map_session_data *target_sd; int trade_i; + int flag; nullpo_retv(sd); - if((target_sd = map_id2sd(sd->trade_partner)) != NULL){ - if( (sd->deal_locked >=1) && (target_sd->deal_locked >=1) ){ // both have pressed 'ok' - if(sd->deal_locked < 2) {sd->deal_locked=2;} // set locked to 2 - if(target_sd->deal_locked==2) { // the other one pressed 'trade' too - for(trade_i=0; trade_i<10;trade_i++) { - if(sd->deal_item_amount[trade_i] != 0) { - int n=sd->deal_item_index[trade_i]-2; - int flag; - - //Dupe Fix by mark - if (sd->status.inventory[n].amount < sd->deal_item_amount[trade_i]) - sd->deal_item_amount[trade_i] = sd->status.inventory[n].amount; - //End Dupe Fix - - #ifndef TXT_ONLY - if(log_config.trade > 0) - log_trade(sd,target_sd,n,sd->deal_item_amount[trade_i]); - #endif //USE_SQL - - flag = pc_additem(target_sd,&sd->status.inventory[n],sd->deal_item_amount[trade_i]); - if(flag==0) - pc_delitem(sd,n,sd->deal_item_amount[trade_i],1); - else - clif_additem(sd,n,sd->deal_item_amount[trade_i],0); - sd->deal_item_index[trade_i] =0; - sd->deal_item_amount[trade_i]=0; - } - if(target_sd->deal_item_amount[trade_i] != 0) { - int n=target_sd->deal_item_index[trade_i]-2; - int flag; - - //Dupe Fix by mark - if (target_sd->status.inventory[n].amount < target_sd->deal_item_amount[trade_i]) - target_sd->deal_item_amount[trade_i] = target_sd->status.inventory[n].amount; - //End Dupe Fix - - #ifndef TXT_ONLY - if(log_config.trade > 0) - log_trade(target_sd,sd,n,target_sd->deal_item_amount[trade_i]); - #endif //USE_SQL - - flag = pc_additem(sd,&target_sd->status.inventory[n],target_sd->deal_item_amount[trade_i]); - if(flag==0) - pc_delitem(target_sd,n,target_sd->deal_item_amount[trade_i],1); - else - clif_additem(target_sd,n,target_sd->deal_item_amount[trade_i],0); - target_sd->deal_item_index[trade_i] =0; - target_sd->deal_item_amount[trade_i]=0; - } + if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) { + if ((sd->deal_locked >= 1) && (target_sd->deal_locked >= 1)) { // both have pressed 'ok' + if (sd->deal_locked < 2) { // set locked to 2 + sd->deal_locked = 2; + } + if (target_sd->deal_locked == 2) { // the other one pressed 'trade' too + // check exploit (trade more items that you have) + if (impossible_trade_check(sd)) { + trade_tradecancel(sd); + return; } - if(sd->deal_zeny) { - #ifndef TXT_ONLY - if (log_config.trade > 0 && log_config.zeny > 0) - log_zeny(sd, target_sd, sd->deal_zeny); - #endif //USE_SQL - sd->status.zeny -= sd->deal_zeny; - clif_updatestatus(sd,SP_ZENY); - target_sd->status.zeny += sd->deal_zeny; - clif_updatestatus(target_sd,SP_ZENY); - sd->deal_zeny=0; + // check exploit (trade more items that you have) + if (impossible_trade_check(target_sd)) { + trade_tradecancel(target_sd); + return; } - if(target_sd->deal_zeny) { - #ifndef TXT_ONLY - if (log_config.trade > 0 && log_config.zeny > 0) - log_zeny(target_sd, sd, target_sd->deal_zeny); - #endif //USE_SQL - target_sd->status.zeny -= target_sd->deal_zeny; - clif_updatestatus(target_sd,SP_ZENY); - sd->status.zeny += target_sd->deal_zeny; - clif_updatestatus(sd,SP_ZENY); - target_sd->deal_zeny=0; + // check zenys value against hackers + if (sd->deal_zeny >= 0 && sd->deal_zeny <= MAX_ZENY && sd->deal_zeny <= sd->status.zeny && // check amount + (target_sd->status.zeny + sd->deal_zeny) <= MAX_ZENY && // fix positiv overflow + target_sd->deal_zeny >= 0 && target_sd->deal_zeny <= MAX_ZENY && target_sd->deal_zeny <= target_sd->status.zeny && // check amount + (sd->status.zeny + target_sd->deal_zeny) <= MAX_ZENY) { // fix positiv overflow + + // trade is accepted + for(trade_i = 0; trade_i < 10; trade_i++) { + if (sd->deal_item_amount[trade_i] != 0) { + int n = sd->deal_item_index[trade_i] - 2; + + if (sd->status.inventory[n].amount < sd->deal_item_amount[trade_i]) + sd->deal_item_amount[trade_i] = sd->status.inventory[n].amount; + log_trade(sd, target_sd, n, sd->deal_item_amount[trade_i]); + + flag = pc_additem(target_sd, &sd->status.inventory[n], sd->deal_item_amount[trade_i]); + if (flag == 0) + pc_delitem(sd, n, sd->deal_item_amount[trade_i], 1); + else + clif_additem(sd, n, sd->deal_item_amount[trade_i], 0); + sd->deal_item_index[trade_i] = 0; + sd->deal_item_amount[trade_i] = 0; + + } + if (target_sd->deal_item_amount[trade_i] != 0) { + int n = target_sd->deal_item_index[trade_i] - 2; + + if (target_sd->status.inventory[n].amount < target_sd->deal_item_amount[trade_i]) + target_sd->deal_item_amount[trade_i] = target_sd->status.inventory[n].amount; + + log_trade(target_sd, sd, n, target_sd->deal_item_amount[trade_i]); + flag = pc_additem(sd, &target_sd->status.inventory[n], target_sd->deal_item_amount[trade_i]); + if (flag == 0) + pc_delitem(target_sd, n, target_sd->deal_item_amount[trade_i], 1); + else + clif_additem(target_sd, n, target_sd->deal_item_amount[trade_i], 0); + target_sd->deal_item_index[trade_i] = 0; + target_sd->deal_item_amount[trade_i] = 0; + } + } + if (sd->deal_zeny) { + sd->status.zeny -= sd->deal_zeny; + target_sd->status.zeny += sd->deal_zeny; + } + if (target_sd->deal_zeny) { + target_sd->status.zeny -= target_sd->deal_zeny; + sd->status.zeny += target_sd->deal_zeny; + } + if (sd->deal_zeny || target_sd->deal_zeny) { + clif_updatestatus(sd, SP_ZENY); + sd->deal_zeny = 0; + clif_updatestatus(target_sd, SP_ZENY); + target_sd->deal_zeny = 0; + } + sd->deal_locked = 0; + sd->trade_partner = 0; + target_sd->deal_locked = 0; + target_sd->trade_partner = 0; + clif_tradecompleted(sd, 0); + clif_tradecompleted(target_sd, 0); + // save both player to avoid crash: they always have no advantage/disadvantage between the 2 players + chrif_save(sd); // do pc_makesavestatus and save storage too + chrif_save(target_sd); // do pc_makesavestatus and save storage too + // zeny value was modified!!!! hacker with packet modified + } else { + trade_tradecancel(sd); } - sd->deal_locked =0; - sd->trade_partner=0; - target_sd->deal_locked=0; - target_sd->trade_partner=0; - clif_tradecompleted(sd,0); - clif_tradecompleted(target_sd,0); } } } diff --git a/src/map/vending.c b/src/map/vending.c index a7aa708e5..2d3790596 100644 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -48,7 +48,7 @@ void vending_vendinglistreq(struct map_session_data *sd,int id) */ void vending_purchasereq(struct map_session_data *sd,int len,int id,unsigned char *p) { - int i, j, w, z, new = 0, blank, vend_list[12]; + int i, j, w, z, new_ = 0, blank, vend_list[12]; short amount, index; struct map_session_data *vsd = map_id2sd(id); @@ -99,8 +99,8 @@ void vending_purchasereq(struct map_session_data *sd,int len,int id,unsigned cha case ADDITEM_EXIST: break; case ADDITEM_NEW: - new++; - if (new > blank) + new_++; + if (new_ > blank) return; // Ží—Þ”’´‰ß break; case ADDITEM_OVERAMOUNT: @@ -112,6 +112,7 @@ void vending_purchasereq(struct map_session_data *sd,int len,int id,unsigned cha clif_tradecancelled(vsd); return; } + pc_payzeny(sd, z); pc_getzeny(vsd, z); for(i = 0; 8 + 4 * i < len; i++) { @@ -122,6 +123,13 @@ void vending_purchasereq(struct map_session_data *sd,int len,int id,unsigned cha vsd->vending[vend_list[i]].amount -= amount; pc_cart_delitem(vsd, index, amount, 0); clif_vendingreport(vsd, index, amount); + + //log added by Lupus + if(log_config.vend > 0) { + log_vend(sd,vsd, index, amount, z); // for Item + Zeny. log. + //we log ZENY only with the 1st item. Then zero it for the rest items 8). + z = 0; + } } } @@ -141,11 +149,14 @@ void vending_openvending(struct map_session_data *sd,int len,char *message,int f } if (flag) { - for(i = 0; 85 + 8 * i < len; i++) { + for(i = 0; (85 + 8 * i < len) && (i < MAX_VENDING); i++) { sd->vending[i].index = *(short*)(p+8*i)-2; sd->vending[i].amount = *(short*)(p+2+8*i); sd->vending[i].value = *(int*)(p+4+8*i); - if(sd->vending[i].value>battle_config.vending_max_value)sd->vending[i].value=battle_config.vending_max_value; + if(sd->vending[i].value > battle_config.vending_max_value) + sd->vending[i].value=battle_config.vending_max_value; + else if(sd->vending[i].value == 0) + sd->vending[i].value = 1000000; // auto set to 1 million [celest] // ƒJ[ƒg“à‚̃AƒCƒeƒ€”‚Ɣ̔„‚·‚éƒAƒCƒeƒ€”‚É‘Šˆá‚ª‚ ‚Á‚½‚ç’†Ž~ if(pc_cartitem_amount(sd, sd->vending[i].index, sd->vending[i].amount) < 0 || sd->vending[i].value < 0) { // fixes by Valaris and fritz clif_skill_fail(sd, MC_VENDING, 0, 0); diff --git a/src/tool/Makefile b/src/tool/Makefile new file mode 100644 index 000000000..bbf18cf98 --- /dev/null +++ b/src/tool/Makefile @@ -0,0 +1,6 @@ +all: + $(CC) -o adduser adduser.c + +clean: + rm -f adduser + rm -f *.exe diff --git a/src/tool/adduser.c b/src/tool/adduser.c new file mode 100644 index 000000000..1219540ab --- /dev/null +++ b/src/tool/adduser.c @@ -0,0 +1,96 @@ +/* + This program adds an user to account.txt + Don't usr it When login-sever is working. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +char *account_txt = "../save/account.txt"; + +//----------------------------------------------------- +// Function to suppress control characters in a string. +//----------------------------------------------------- +int remove_control_chars(unsigned char *str) { + int i; + int change = 0; + + for(i = 0; str[i]; i++) { + if (str[i] < 32) { + str[i] = '_'; + change = 1; + } + } + + return change; +} + +int main(int argc, char *argv[]) { + + char username[24]; + char password[24]; + char sex[2]; + + int next_id, id; + char line[1024]; + + // Check to see if account.txt exists. + printf("Checking if '%s' file exists...\n", account_txt); + FILE *FPaccin = fopen(account_txt, "r"); + if (FPaccin == NULL) { + printf("'%s' file not found!\n", account_txt); + printf("Run the setup wizard please.\n"); + exit(0); + } + + next_id = 2000000; + while(fgets(line, sizeof(line)-1, FPaccin)) { + if (line[0] == '/' && line[1] == '/') { continue; } + if (sscanf(line, "%d\t%%newid%%\n", &id) == 1) { + if (next_id < id) { + next_id = id; + } + } else { + sscanf(line,"%i%[^ ]", &id); + if (next_id <= id) { + next_id = id +1; + } + } + } + close(FPaccin); + printf("File exists.\n"); + + printf("Don't create an account if the login-server is online!!!\n"); + printf("If the login-server is online, press ctrl+C now to stop this software.\n"); + printf("\n"); + + strcpy(username, ""); + while (strlen(username) < 4 || strlen(username) > 23) { + printf("Enter an username (4-23 characters): "); + scanf("%s", &username); + username[23] = 0; + remove_control_chars(username); + } + + strcpy(password, ""); + while (strlen(password) < 4 || strlen(password) > 23) { + printf("Enter a password (4-23 characters): "); + scanf("%s", &password); + password[23] = 0; + remove_control_chars(password); + } + + strcpy(sex, ""); + while (strcmp(sex, "F") != 0 && strcmp(sex, "M") != 0) { + printf("Enter a gender (M for male, F for female): "); + scanf("%s", &sex); + } + + FILE *FPaccout = fopen(account_txt, "r+"); + fseek(FPaccout, 0, SEEK_END); + fprintf(FPaccout, "%i %s %s - %s -\r\n", next_id, username, password, sex); + close(FPaccout); + + printf("Account added.\n"); +} diff --git a/src/tool/backup b/src/tool/backup new file mode 100644 index 000000000..939c7eee7 --- /dev/null +++ b/src/tool/backup @@ -0,0 +1,100 @@ +#!/usr/bin/perl + +########################################################################## +# Athena—pƒf[ƒ^ƒoƒbƒNƒAƒbƒvƒc[ƒ‹ +# +# @Athena‚ÌŠeŽíƒf[ƒ^ƒtƒ@ƒCƒ‹*.txt‚ðƒoƒbƒNƒAƒbƒv‚·‚éƒc[ƒ‹ +# +#------------------------------------------------------------------------- +# Ý’è•û–@ +# @ŽÀs‚·‚鎞‚̃JƒŒƒ“ƒgƒtƒHƒ‹ƒ_‚©‚ç‚̃f[ƒ^‚ւ̃pƒXAƒtƒ@ƒCƒ‹‚ÌƒŠƒXƒg‚ð +# @³‚µ‚ݒ肵‚Ü‚·BƒoƒbƒNƒAƒbƒvæ‚̃tƒHƒ‹ƒ_‚ÍŽ©“®ì¬‚³‚ê‚È‚¢‚Ì‚ÅA +# @Ž©•ª‚Å쬂µ‚Ä‚¨‚•K—v‚ª‚ ‚è‚Ü‚·B +# @ƒtƒHƒ‹ƒ_‚ÌÅŒã‚Ìu/v‚ÍÈ—ª‚Å‚«‚Ü‚¹‚ñB +# +# @ƒtƒHƒ‹ƒ_‚͈ø”‚Å‚àŽw’è‚Å‚«‚Ü‚·B—á„./backup ../save/ ./backup_data/ +# @ƒtƒHƒ‹ƒ_‚ÌÅŒã‚Ìu/v‚ÍÈ—ª‚Å‚«‚Ü‚¹‚ñB +# +# @ŽÀs‚·‚邯ƒoƒbƒNƒAƒbƒvæ‚̃tƒHƒ‹ƒ_‚ÖAƒtƒ@ƒCƒ‹–¼‚ÉŒ»Ý‚Ì“ú•t‚ÆŽž‚ð +# @‚‚¯‚ătƒ@ƒCƒ‹‚ðƒRƒs[‚µ‚Ü‚·B +# +# * toolƒtƒHƒ‹ƒ_“à‚Ébackup_dataƒtƒHƒ‹ƒ_‚ð쬂µA +# @ athena.sh‚Ì’†‚Éu./tool/backup ./save/ ./tool/backup_data/v +# ‚Æ‚¢‚¤s‚ð’ljÁ‚·‚邯Aathena‚ð‹N“®‚·‚邽‚тɃoƒbƒNƒAƒbƒv‚ªŽæ‚ê‚Ü‚· +# +# •œŒ³‚·‚邯‚«‚͈ø”‚Éu-r “ú•t‚ÆŽžv‚ðŽw’肵‚Ü‚·B +# @‚Ü‚½‚»‚ÌŒã‚ë‚ɃtƒHƒ‹ƒ_‚ðŽw’è‚·‚邱‚Æ‚ào—ˆ‚Ü‚· +# @—á‚P„ ./backup -r 200309191607 +# @—á‚Q„ ./backup -r 200309191607 ../save ./backup_data/ +# @‚±‚Ì—á‚Å‚Í2003/09/19‚Ì16:07•ª‚ɃoƒbƒNƒAƒbƒv‚µ‚½ƒf[ƒ^‚𕜌³‚µ‚Ä‚¢‚Ü‚· +# +# @•œŒ³‚·‚邯‚«AAthenaƒfƒBƒŒƒNƒgƒŠ‚É‚ ‚éƒf[ƒ^‚Í *.bak ‚É–¼‘O‚ð•ÏX‚µ‚Ä +# @Žc‚µ‚Ä‚¢‚é‚Ì‚ÅA‚¢‚ç‚È‚¢ê‡‚Í rm *.bak ‚ȂǂÅÁ‚µ‚Ä‚‚¾‚³‚¢B +# +########################################################################## + +$sdir="../save/"; #ƒoƒbƒNƒAƒbƒvŒ³(Athena‚̃fƒBƒŒƒNƒgƒŠ/save/) +$tdir="./backup_data/"; #ƒoƒbƒNƒAƒbƒvæ + +@files=( #ƒtƒ@ƒCƒ‹‚ÌƒŠƒXƒg + "account","athena","storage","party","guild","castle","pet" +); + + +#-------------------------------ݒ肱‚±‚Ü‚Å----------------------------- + + + + + + + + + + + +if($ARGV[0]=~/^\-r$/i || $ARGV[0]=~/\-\-(recover|restore)/i){ + #•œŒ³ˆ— + + $file=$ARGV[1]; + $sdir=$ARGV[2]||$sdir; + $tdir=$ARGV[3]||$tdir; + &restorecopy($_) foreach @files; + exit(0); +} + +#ƒoƒbƒNƒAƒbƒvˆ— +$sdir=$ARGV[0]||$sdir; +$tdir=$ARGV[1]||$tdir; + +unless( -d $tdir ){ + print "$0: \"$tdir\" : No such directory\n"; + exit(1); +} + +(undef,$min,$hour,$day,$month,$year)=localtime; + +$file=sprintf("%04d%02d%02d%02d%02d", + $year+1900, $month+1, $day, $hour, $min ); + +&backupcopy($_) foreach @files; +exit(0); + +sub backupcopy { + my($name)= @_; + system("cp $sdir$name.txt $tdir$name$file.txt"); +} + +sub restorecopy { + my($name)= @_; + unless( -f "$sdir$name.txt" ){ + printf("$0: \"$sdir$name.txt\" not found!\n"); + return 0; + } + unless( -f "$tdir$name$file.txt" ){ + printf("$0: \"$tdir$name$file.txt\" not found!\n"); + return 0; + } + rename "$sdir$name.txt","$sdir$name.bak"; + system("cp $tdir$name$file.txt $sdir$name.txt"); +} diff --git a/src/tool/cgi/addaccount.cgi b/src/tool/cgi/addaccount.cgi new file mode 100644 index 000000000..7d1788c48 --- /dev/null +++ b/src/tool/cgi/addaccount.cgi @@ -0,0 +1,204 @@ +#!/usr/bin/perl + +#========================================================================= +# addaccount.cgi ver.1.00 +# ladmin‚ðƒ‰ƒbƒv‚µ‚½AƒAƒJƒEƒ“ƒg‚ð쬂·‚éCGIB +# ladmin ver.1.04‚ł̓®ì‚ðŠm”FB +# +# ** Ý’è•û–@ ** +# +# - ‰º‚Ì$ladmin•Ï”‚Éladmin‚ւ̃pƒX‚ðÝ’è‚·‚邱‚ÆB +# - UNIXŒnOS‚ÅŽg—p‚·‚éꇂÍladmin‚Æ‹¤‚ɉüsƒR[ƒh‚ð•ÏŠ·‚·‚邱‚ÆA‚Ü‚½ +# ƒtƒ@ƒCƒ‹æ“ªs‚ðperl‚̳‚µ‚¢ƒpƒX‚É‚·‚邱‚ÆB—á> $ which perl +# - ƒT[ƒo[ƒvƒƒOƒ‰ƒ€‚âƒuƒ‰ƒEƒU‚É‚æ‚Á‚Ä‚Í $cgiuri ‚É‚±‚̃tƒ@ƒCƒ‹‚Ö‚Ì +# Š®‘S‚ÈURI‚ðƒZƒbƒg‚µ‚È‚¯‚ê‚΂Ȃç‚È‚¢ê‡‚à‚ ‚éB +# - perl‚ɃpƒX‚ª’Ê‚Á‚Ä‚¢‚È‚¢ê‡‚Í $perl ‚ðperl‚ւ̳‚µ‚¢ƒpƒX‚É‚·‚邱‚ÆB +# - ‘¼‚Í•’Ê‚ÌCGI‚Æ“¯‚¶‚Å‚·BiŽÀsŒ ‚âcgi-binƒtƒHƒ‹ƒ_‚È‚Çj +# +# ** ‚»‚Ì‘¼ ** +# addaccount.cgi ‚ðƒuƒ‰ƒEƒU‚ÅŠJ‚‚ƃTƒ“ƒvƒ‹HTMLi‚»‚̂܂܎g‚¦‚Ü‚·j‚ª +# ŠJ‚«‚Ü‚·B‚Ü‚½A‚±‚Ìcgi‚̓uƒ‰ƒEƒU‚©‚ç‘—‚ç‚ê‚éAccept-Language‚ª +# ja‚ÅŽn‚Ü‚Á‚Ä‚¢‚ê‚΃ƒbƒZ[ƒW‚̈ꕔ‚ð“ú–{Œê‚ɕϊ·‚µ‚Ü‚·B +# (IE‚È‚çƒCƒ“ƒ^[ƒlƒbƒgƒIƒvƒVƒ‡ƒ“‚ÌŒ¾ŒêÝ’è‚ňê”Ôã‚É“ú–{Œê‚ð’u‚) +# ‚»‚êˆÈŠO‚Ìꇂ͉pŒê‚̂܂Üo—Í‚µ‚Ü‚·B +#------------------------------------------------------------------------- + +my($ladmin) = "../ladmin"; # ladmin‚̃pƒX(‚¨‚»‚ç‚•ÏX‚ª•K—v) + +my($cgiuri) = "./addaccount.cgi"; # ‚±‚̃tƒ@ƒCƒ‹‚ÌURI +my($perl) = "perl"; # perl‚̃Rƒ}ƒ“ƒh–¼ + + + +#--------------------------- ݒ肱‚±‚܂Š-------------------------------- + + + + + + +use strict; +use CGI; + +my($cgi)= new CGI; +my(%langconv)=( + 'Athena login-server administration tool.*' => '', + 'logged on.*' => '', +); + +# ----- “ú–{ŒêŠÂ‹«‚È‚ç•ÏŠ·ƒe[ƒuƒ‹‚ðƒZƒbƒg ----- +if($ENV{'HTTP_ACCEPT_LANGUAGE'}=~/^ja/){ + my(%tmp)=( + 'Account \[(.+)\] is successfully created.*' + => 'ƒAƒJƒEƒ“ƒg "$1" ‚ð쬂µ‚Ü‚µ‚½.', + 'Account \[(.+)\] creation failed\. same account exists.*' + => 'ƒAƒJƒEƒ“ƒg "$1" ‚ÍŠù‚É‘¶Ý‚µ‚Ü‚·.', + 'Illeagal charactor found in UserID.*' + => 'ID‚Ì’†‚É•s³‚È•¶Žš‚ª‚ ‚è‚Ü‚·.', + 'Illeagal charactor found in Password.*' + => 'Password‚Ì’†‚É•s³‚È•¶Žš‚ª‚ ‚è‚Ü‚·.', + 'input UserID 4-24 bytes.' + => 'ID‚Í”¼Šp4`24•¶Žš‚Å“ü—Í‚µ‚Ä‚‚¾‚³‚¢.', + 'input Password 4-24 bytes.' + => 'Password‚Í”¼Šp4`24•¶Žš‚Å“ü—Í‚µ‚Ä‚‚¾‚³‚¢.', + 'Illeagal gender.*' + => '«•Ê‚ª‚¨‚©‚µ‚¢‚Å‚·.', + 'Cant connect to login server.*' + => 'ƒƒOƒCƒ“ƒT[ƒo[‚ÉÚ‘±‚Å‚«‚Ü‚¹‚ñ.', + 'login error.*' + => 'ƒƒOƒCƒ“ƒT[ƒo[‚Ö‚ÌŠÇ—ŽÒŒ ŒÀƒƒOƒCƒ“‚ÉŽ¸”s‚µ‚Ü‚µ‚½', + "Can't execute ladmin.*" + => 'ladmin‚ÌŽÀs‚ÉŽ¸”s‚µ‚Ü‚µ‚½', + 'UserID "(.+)" is already used.*' + => 'ID "$1" ‚ÍŠù‚ÉŽg—p‚³‚ê‚Ä‚¢‚Ü‚·.', + 'You can use UserID \"(.+)\".*' + => 'ID "$1" ‚ÍŽg—p‰Â”\‚Å‚·.', + + 'account making' =>'ƒAƒJƒEƒ“ƒgì¬', + '\>UserID' =>'>‚h‚c', + '\>Password' =>'>ƒpƒXƒ[ƒh', + '\>Gender' =>'>«•Ê', + '\>Male' =>'>’j«', + '\>Female' =>'>—«', + '\"Make Account\"' =>'"ƒAƒJƒEƒ“ƒgì¬"', + '\"Check UserID\"' =>'"ID‚̃`ƒFƒbƒN"', + ); + map { $langconv{$_}=$tmp{$_}; } keys (%tmp); +} + +# ----- ’ljÁ ----- +if( $cgi->param("addaccount") ){ + my($userid)= $cgi->param("userid"); + my($passwd)= $cgi->param("passwd"); + my($gender)= lc(substr($cgi->param("gender"),0,1)); + if(length($userid)<4 || length($userid)>24){ + HttpError("input UserID 4-24 bytes."); + } + if(length($passwd)<4 || length($passwd)>24){ + HttpError("input Password 4-24 bytes."); + } + if($userid=~/[^0-9A-Za-z\@\_\-\']/){ + HttpError("Illeagal charactor found in UserID."); + } + if($passwd=~/[\x00-\x1f\x80-\xff\']/){ + HttpError("Illeagal charactor found in Password."); + } + if($gender!~/[mf]/){ + HttpError("Gender error."); + } + open PIPE,"$perl $ladmin --add $userid $gender $passwd |" + or HttpError("Can't execute ladmin."); + my(@msg)=<PIPE>; + close PIPE; + HttpMsg(@msg); +} +# ----- ‘¶Ýƒ`ƒFƒbƒN ----- +elsif( $cgi->param("check") ){ + my($userid)= $cgi->param("userid"); + if(length($userid)<4 || length($userid)>24){ + HttpError("input UserID 4-24 bytes."); + } + if($userid=~/[^0-9A-Za-z\@\_\-\']/){ + HttpError("Illeagal charactor found in UserID."); + } + open PIPE,"$perl $ladmin --search --regex \\b$userid\\b |" + or HttpError("Can't execute ladmin."); + my(@msg)=<PIPE>; + close PIPE; + if(scalar(@msg)==6 && (split /[\s\0]+/,substr($msg[4],11,24))[0] eq $userid){ + HttpMsg("NG : UserID \"$userid\" is already used."); + }elsif(scalar(@msg)==5){ + HttpMsg("OK : You can use UserID \"$userid\""); + } + HttpError("ladmin error ?\n---output---\n",@msg); +} + +# ----- ƒtƒH[ƒ€ ----- +else{ + print LangConv( <<"EOM" ); +Content-type: text/html\n +<html> + <head> + <title>Athena account making cgi</title> + </head> + <body> + <h1>Athena account making cgi</h1> + <form action="$cgiuri" method="post"> + <table border=2> + <tr> + <th>UserID</th> + <td><input name="userid" size=24 maxlength=24></td> + </tr> + <tr> + <th>Password</th> + <td><input name="passwd" size=24 maxlength=24 type="password"></td> + </tr> + <tr> + <th>Gender</th> + <td> + <input type="radio" name="gender" value="male">Male + <input type="radio" name="gender" value="female">Female + </td> + </tr> + <tr> + <td colspan=2> + <input type="submit" name="addaccount" value="Make Account"> + <input type="submit" name="check" value="Check UserID"> + </td> + </tr> + </table> + </form> + </body> +</html> +EOM + exit; +} + +sub LangConv { + my(@lst)= @_; + my($a,$b,@out)=(); + foreach $a(@lst){ + foreach $b(keys %langconv){ + $a=~s/$b/$langconv{$b}/g; + my($rep1)=$1; + $a=~s/\$1/$rep1/g; + } + push @out,$a; + } + return @out; +} + +sub HttpMsg { + my($msg)=join("", LangConv(@_)); + $msg=~s/\n/<br>\n/g; + print LangConv("Content-type: text/html\n\n"),$msg; + exit; +} + +sub HttpError { + my($msg)=join("", LangConv(@_)); + $msg=~s/\n/<br>\n/g; + print LangConv("Content-type: text/html\n\n"),$msg; + exit; +} + diff --git a/src/tool/checkversion b/src/tool/checkversion new file mode 100644 index 000000000..9e485d9a3 --- /dev/null +++ b/src/tool/checkversion @@ -0,0 +1,85 @@ +#!/usr/bin/perl -w + +########################################################################## +# INFORMATION TOOL ABOUT THE SERVERS VERSION OF ATHENA +# +# By connection on a server, this software display the version of the +# designed server. +#------------------------------------------------------------------------- +# Usages: +# ./checkversion IP:port +# ./checkversion IP port +# perl checkversion IP:port +# perl checkversion IP port +# +# note: default port: 6900 +# +# When successfull, the software return the value 0. +# +########################################################################## + +#------------------------- start of configuration ------------------------ + +$connecttimeout = 10; # Connection Timeout (in seconds) + +#-------------------------- End of configuration ------------------------- + +use IO::Socket; + +unless($ARGV[0]) { + print "USAGE: $0 server_ip:port\n"; + exit(1); +} + +$server = $ARGV[0]; +$port = $ARGV[1]; +$port = $1 if ($server =~ s/:(\d+)//); +$port ||= 6900; + +# Connection to the server +my($so,$er) = (); +eval{ + $so = IO::Socket::INET->new( + PeerAddr=> $server, + PeerPort=> $port, + Proto => "tcp", + Timeout => $connecttimeout) or $er = 1; +}; + +if($er || $@) { + print "Can't not connect to server [$server:$port] !\n"; + exit(2); +} + +# Request for the server version +print $so pack("v",30000); # 0x7530 +$so->flush(); + +# Receiving of the answer of the server +if (read($so,$buf,10) < 10) { + print "Invalid answer. It isn't an athena server or it is a too old version.\n"; + exit(5); +} + +# Sending end of connection to the server +print $so pack("v",30002); # 0x7532 +$so->flush(); + +# Analyse of the answer +my($ret,$maver,$miver,$rev,$dev,$mod,$type,$mdver) = unpack("v c6 v",$buf); + +if ($ret != 30001) { # 0x7531 + print "Invalid answer. It isn't an athena server or it is a too old version.\n"; + exit(6); +} + +my(@stype) = (); +foreach $i(0..3) { + push @stype,(("login","char","inter","map")[$i]) if( $type & (1<<$i) ); +} +print " ".join("/",@stype)." server [$server:$port].\n"; +printf " Athena version %s-%d.%d", ("stable","dev")[$dev], $maver,$miver; +printf " revision %d",$rev if $rev; +printf "%s%d\n",("","-mod")[$mod],$mdver; + +exit(0); diff --git a/src/tool/convert.c b/src/tool/convert.c new file mode 100644 index 000000000..16631c945 --- /dev/null +++ b/src/tool/convert.c @@ -0,0 +1,296 @@ +#include <stdio.h> +#include <stdlib.h> + +#define RETCODE "\r\n" + +#define MAX_INVENTORY 100 +#define MAX_CART 100 +#define MAX_SKILL 350 +#define GLOBAL_REG_NUM 16 + +struct item { + int id; + short nameid; + short amount; + short equip; + char identify; + char refine; + char attribute; + short card[4]; +}; +struct point{ + char map[16]; + short x,y; +}; +struct skill { + unsigned short id,lv,flag; +}; +struct global_reg { + char str[16]; + int value; +}; + +struct mmo_charstatus { + int char_id; + int account_id; + int base_exp,job_exp,zeny; + + short class; + short status_point,skill_point; + short hp,max_hp,sp,max_sp; + short option,karma,manner; + short hair,hair_color,clothes_color; + int party_id,guild_id,pet_id; + + short weapon,shield; + short head_top,head_mid,head_bottom; + + char name[24]; + unsigned char base_level,job_level; + unsigned char str,agi,vit,int_,dex,luk,char_num,sex; + + struct point last_point,save_point,memo_point[3]; + struct item inventory[MAX_INVENTORY],cart[MAX_CART]; + struct skill skill[MAX_SKILL]; + int global_reg_num; + struct global_reg global_reg[GLOBAL_REG_NUM]; +}; + +int mmo_char_tostr(char *str,struct mmo_charstatus *p) +{ + int i; + sprintf(str,"%d\t%d,%d\t%s\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" + "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" + "\t%s,%d,%d\t%s,%d,%d", + p->char_id,p->account_id,p->char_num,p->name, // + p->class,p->base_level,p->job_level, + p->base_exp,p->job_exp,p->zeny, + p->hp,p->max_hp,p->sp,p->max_sp, + p->str,p->agi,p->vit,p->int_,p->dex,p->luk, + p->status_point,p->skill_point, + p->option,p->karma,p->manner, // + p->party_id,p->guild_id,p->pet_id, + p->hair,p->hair_color,p->clothes_color, + p->weapon,p->shield,p->head_top,p->head_mid,p->head_bottom, + p->last_point.map,p->last_point.x,p->last_point.y, // + p->save_point.map,p->save_point.x,p->save_point.y + ); + strcat(str,"\t"); + for(i=0;i<3;i++) + if(p->memo_point[i].map[0]){ + sprintf(str+strlen(str),"%s,%d,%d",p->memo_point[i].map,p->memo_point[i].x,p->memo_point[i].y); + } + strcat(str,"\t"); + for(i=0;i<MAX_INVENTORY;i++) + if(p->inventory[i].nameid){ + sprintf(str+strlen(str),"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ", + p->inventory[i].id,p->inventory[i].nameid,p->inventory[i].amount,p->inventory[i].equip, + p->inventory[i].identify,p->inventory[i].refine,p->inventory[i].attribute, + p->inventory[i].card[0],p->inventory[i].card[1],p->inventory[i].card[2],p->inventory[i].card[3]); + } + strcat(str,"\t"); + for(i=0;i<MAX_CART;i++) + if(p->cart[i].nameid){ + sprintf(str+strlen(str),"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ", + p->cart[i].id,p->cart[i].nameid,p->cart[i].amount,p->cart[i].equip, + p->cart[i].identify,p->cart[i].refine,p->cart[i].attribute, + p->cart[i].card[0],p->cart[i].card[1],p->cart[i].card[2],p->cart[i].card[3]); + } + strcat(str,"\t"); + for(i=0;i<MAX_SKILL;i++) + if(p->skill[i].id){ + sprintf(str+strlen(str),"%d,%d ",p->skill[i].id,p->skill[i].lv); + } + strcat(str,"\t"); + for(i=0;i<p->global_reg_num;i++) + sprintf(str+strlen(str),"%s,%d ",p->global_reg[i].str,p->global_reg[i].value); + strcat(str,"\t"); + return 0; +} + +int mmo_char_fromstr(char *str,struct mmo_charstatus *p) +{ + int tmp_int[256]; + int set,next,len,i; + + set=sscanf(str,"%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" + "\t%d,%d,%d\t%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" + "\t%[^,],%d,%d\t%[^,],%d,%d%n", + &tmp_int[0],&tmp_int[1],&tmp_int[2],p->name, // + &tmp_int[3],&tmp_int[4],&tmp_int[5], + &tmp_int[6],&tmp_int[7],&tmp_int[8], + &tmp_int[9],&tmp_int[10],&tmp_int[11],&tmp_int[12], + &tmp_int[13],&tmp_int[14],&tmp_int[15],&tmp_int[16],&tmp_int[17],&tmp_int[18], + &tmp_int[19],&tmp_int[20], + &tmp_int[21],&tmp_int[22],&tmp_int[23], // + &tmp_int[24],&tmp_int[25], + &tmp_int[26],&tmp_int[27],&tmp_int[28], + &tmp_int[29],&tmp_int[30],&tmp_int[31],&tmp_int[32],&tmp_int[33], + p->last_point.map,&tmp_int[34],&tmp_int[35], // + p->save_point.map,&tmp_int[36],&tmp_int[37],&next + ); + p->char_id=tmp_int[0]; + p->account_id=tmp_int[1]; + p->char_num=tmp_int[2]; + p->class=tmp_int[3]; + p->base_level=tmp_int[4]; + p->job_level=tmp_int[5]; + p->base_exp=tmp_int[6]; + p->job_exp=tmp_int[7]; + p->zeny=tmp_int[8]; + p->hp=tmp_int[9]; + p->max_hp=tmp_int[10]; + p->sp=tmp_int[11]; + p->max_sp=tmp_int[12]; + p->str=tmp_int[13]; + p->agi=tmp_int[14]; + p->vit=tmp_int[15]; + p->int_=tmp_int[16]; + p->dex=tmp_int[17]; + p->luk=tmp_int[18]; + p->status_point=tmp_int[19]; + p->skill_point=tmp_int[20]; + p->option=tmp_int[21]; + p->karma=tmp_int[22]; + p->manner=tmp_int[23]; + p->party_id=tmp_int[24]; + p->guild_id=tmp_int[25]; + p->pet_id=0; + p->hair=tmp_int[26]; + p->hair_color=tmp_int[27]; + p->clothes_color=tmp_int[28]; + p->weapon=tmp_int[29]; + p->shield=tmp_int[30]; + p->head_top=tmp_int[31]; + p->head_mid=tmp_int[32]; + p->head_bottom=tmp_int[33]; + p->last_point.x=tmp_int[34]; + p->last_point.y=tmp_int[35]; + p->save_point.x=tmp_int[36]; + p->save_point.y=tmp_int[37]; + if(set!=41) + return 0; + if(str[next]=='\n' || str[next]=='\r') + return 1; // V‹Kƒf[ƒ^ + next++; + for(i=0;str[next] && str[next]!='\t';i++){ + set=sscanf(str+next,"%[^,],%d,%d%n",p->memo_point[i].map,&tmp_int[0],&tmp_int[1],&len); + if(set!=3) + return 0; + p->memo_point[i].x=tmp_int[0]; + p->memo_point[i].y=tmp_int[1]; + next+=len; + if(str[next]==' ') + next++; + } + next++; + for(i=0;str[next] && str[next]!='\t';i++){ + set=sscanf(str+next,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", + &tmp_int[0],&tmp_int[1],&tmp_int[2],&tmp_int[3], + &tmp_int[4],&tmp_int[5],&tmp_int[6], + &tmp_int[7],&tmp_int[8],&tmp_int[9],&tmp_int[10],&len); + if(set!=11) + return 0; + p->inventory[i].id=tmp_int[0]; + p->inventory[i].nameid=tmp_int[1]; + p->inventory[i].amount=tmp_int[2]; + p->inventory[i].equip=tmp_int[3]; + p->inventory[i].identify=tmp_int[4]; + p->inventory[i].refine=tmp_int[5]; + p->inventory[i].attribute=tmp_int[6]; + p->inventory[i].card[0]=tmp_int[7]; + p->inventory[i].card[1]=tmp_int[8]; + p->inventory[i].card[2]=tmp_int[9]; + p->inventory[i].card[3]=tmp_int[10]; + next+=len; + if(str[next]==' ') + next++; + } + next++; + for(i=0;str[next] && str[next]!='\t';i++){ + set=sscanf(str+next,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", + &tmp_int[0],&tmp_int[1],&tmp_int[2],&tmp_int[3], + &tmp_int[4],&tmp_int[5],&tmp_int[6], + &tmp_int[7],&tmp_int[8],&tmp_int[9],&tmp_int[10],&len); + if(set!=11) + return 0; + p->cart[i].id=tmp_int[0]; + p->cart[i].nameid=tmp_int[1]; + p->cart[i].amount=tmp_int[2]; + p->cart[i].equip=tmp_int[3]; + p->cart[i].identify=tmp_int[4]; + p->cart[i].refine=tmp_int[5]; + p->cart[i].attribute=tmp_int[6]; + p->cart[i].card[0]=tmp_int[7]; + p->cart[i].card[1]=tmp_int[8]; + p->cart[i].card[2]=tmp_int[9]; + p->cart[i].card[3]=tmp_int[10]; + next+=len; + if(str[next]==' ') + next++; + } + next++; + for(i=0;str[next] && str[next]!='\t';i++){ + set=sscanf(str+next,"%d,%d%n", + &tmp_int[0],&tmp_int[1],&len); + if(set!=2) + return 0; + p->skill[tmp_int[0]].id=tmp_int[0]; + p->skill[tmp_int[0]].lv=tmp_int[1]; + next+=len; + if(str[next]==' ') + next++; + } + next++; + for(i=0;str[next] && str[next]!='\t' && str[next]!='\n' && str[next]!='\r';i++){ //global_regŽÀ‘•ˆÈ‘O‚Ìathena.txtŒÝŠ·‚Ì‚½‚߈ꉞ'\n'ƒ`ƒFƒbƒN + set=sscanf(str+next,"%[^,],%d%n", + p->global_reg[i].str,&p->global_reg[i].value,&len); + if(set!=2) + return 0; + next+=len; + if(str[next]==' ') + next++; + } + p->global_reg_num=i; + return 1; +} + +int mmo_char_convert(char *fname1,char *fname2) +{ + char line[65536]; + int ret; + struct mmo_charstatus char_dat; + FILE *ifp,*ofp; + + ifp=fopen(fname1,"r"); + ofp=fopen(fname2,"w"); + if(ifp==NULL) { + printf("file not found %s\n",fname1); + return 0; + } + if(ofp==NULL) { + printf("file open error %s\n",fname2); + return 0; + } + while(fgets(line,65535,ifp)){ + memset(&char_dat,0,sizeof(struct mmo_charstatus)); + ret=mmo_char_fromstr(line,&char_dat); + if(ret){ + mmo_char_tostr(line,&char_dat); + fprintf(ofp,"%s" RETCODE,line); + } + } + fcloseall(); + return 0; +} + +int main(int argc,char *argv[]) +{ + if(argc < 3) { + printf("Usage: convert <input filename> <output filename>\n"); + exit(0); + } + mmo_char_convert(argv[1],argv[2]); + + return 0; +} diff --git a/src/tool/getlogincount b/src/tool/getlogincount new file mode 100644 index 000000000..45c6f81f6 --- /dev/null +++ b/src/tool/getlogincount @@ -0,0 +1,122 @@ +#!/usr/bin/perl -w + +########################################################################## +# INFORMATION TOOL ABOUT THE # OF ONLINE PLAYERS ON ATHENA SERVERS +# +# By connection on the athena login-server, this software displays the +# number of online players. +# +#------------------------------------------------------------------------- +# Software usage: +# Configure the IP, the port and a valid account of the server. +# After, use at your choice: +# ./getlogincount - display the number of online players on all servers. +# ./getlogincount --premier or +# ./getlogincount --first -- display the number of online players of the +# first server in the received list. +# ./getlogincount [servername] -- display the number of online players +# of the specified server. +# +# If successfull, the software return the value 0. +# +########################################################################## + +#------------------------------ CONFIGURATION ---------------------------- + +$loginserverip = "127.0.0.1"; # IP of the login-server +$loginserverport = 6900; # port of the login-server +$loginaccount = "s1"; # a valid account name +$loginpasswd = "p1"; # the password of the valid account name + +$connecttimeout = 10; # Connection timeout (in seconds) + +#------------------------------------------------------------------------- + +use IO::Socket; + +my($sname) = $ARGV[0]; +if (!defined($sname)) { + $sname = ""; +} + +# Connection to the login-server +my($so,$er) = (); +eval{ + $so = IO::Socket::INET->new( + PeerAddr=> $loginserverip, + PeerPort=> $loginserverport, + Proto => "tcp", + Timeout => $connecttimeout) or $er=1; +}; +if($er || $@){ + print "Can't not connect to the login-server [${loginserverip}:$loginserverport] !\n"; + exit(2); +} + +# Request to connect on login-server +print $so pack("v V a24 a24 C",0x0064,9,$loginaccount,$loginpasswd,3); +$so->flush(); + +# Fail to connect +if(unpack("v", &soread(\$so,2)) != 0x0069) { + print "Login error.\n"; + exit(3); +} + +# Get length of the received packet +my($plen) = unpack("v",&soread(\$so,2))-4; + +# Suppress information of the account (we need only information about the servers) +&soread(\$so,43); +$plen -= 43; + +# Check about the number of online servers +if ($plen < 32) { + printf "No server is connected to login-server.\n"; + exit(1); +} + +# Read information of the servers +my(@slist) = (); +for(;$plen > 0;$plen -= 32) { + my($name,$count) = unpack("x6 a20 V",&soread(\$so,32)); + $name = substr($name,0,index($name,"\0")); + push @slist, [ $name, $count ]; +} + +# Display the result +if($sname eq "--first" || $sname eq "--premier") { # If we ask only for the first server + printf "%-20s : %5d\n",$slist[0][0],$slist[0][1]; +} elsif ($sname eq "") { # If we ask for all servers + foreach $i(@slist) { + printf "%-20s : %5d\n",$i->[0],$i->[1]; + } +} else { # If we ask for a specified server (by its name) + my($flag) = 1; + foreach $i(@slist) { + if($i->[0] eq $sname) { + printf "%-20s : %5d\n",$i->[0],$i->[1]; + $flag = 0; + } + } + if($flag) { # If the server doesn't exist + printf "The server [$sname] doesn't exist.\n"; + exit(1); + } +} + +# End of the software +$so->shutdown(2); +$so->close(); +exit(0); + +# Sub-function: get data from the socket +sub soread { + my($so,$len) = @_; + my($sobuf); + if(read($$so,$sobuf,$len) < $len) { + print "Socket read error.\n"; + exit(5); + } + return $sobuf; +}; diff --git a/src/tool/ladmin b/src/tool/ladmin new file mode 100644 index 000000000..d0c0be485 --- /dev/null +++ b/src/tool/ladmin @@ -0,0 +1,3793 @@ +#!/usr/bin/perl +use POSIX; +########################################################################## +# EAthena login-server remote administration tool +# New ladamin by [Yor] +########################################################################## +#-------------------------------INSTRUCTIONS------------------------------ +# Set the 4 variables below: +# IP of the login server. +# Port where the login-server listens incoming packets. +# Password of administration (same of config_athena.conf). +# Displayed language of the sofware (if not correct, english is used). +# IMPORTANT: +# Be sure that you authorize remote administration in login-server +# (see login_athena.conf, 'admin_state' parameter) +#------------------------------------------------------------------------- +my($loginserverip) = "127.0.0.1"; # IP of login-server +my($loginserverport) = 6900; # Port of login-server +my($loginserveradminpassword) = "admin"; # Administration password +my($connecttimeout) = 10; # Timeout of connection (in seconds) +my($passenc) = 2; # Encoding type of the password +my($defaultlanguage) = "E"; # Default language (F: Français/E: English) + # (if it's not 'F', default is English) + +#------------------------------------------------------------------------- +# LIST of COMMANDs that you can type at the prompt: +# To use these commands you can only type only the first letters. +# You must type a minimum of letters (you can not type 'a', +# because ladmin doesn't know if it's for 'aide' or for 'add') +# <Example> q <= quit, li <= list, pass <= passwd, etc. +# +# Note: every time you must give a account_name, you can use "" or '' (spaces can be included) +# +# aide/help/? +# Display the description of the commands +# aide/help/? [command] +# Display the description of the specified command +# +# add <account_name> <sex> <password> +# Create an account with the default email (a@a.com). +# Concerning the sex, only the first letter is used (F or M). +# The e-mail is set to a@a.com (default e-mail). It's like to have no e-mail. +# When the password is omitted, the input is done without displaying of the pressed keys. +# <example> add testname Male testpass +# +# ban/banish yyyy/mm/dd hh:mm:ss <account name> +# Changes the final date of a banishment of an account. +# Same command of banset, except that account_name is at end +# +# banadd <account_name> <modifier> +# Adds or substracts time from the final date of a banishment of an account. +# Modifier is done as follows: +# Adjustment value (-1, 1, +1, etc...) +# Modified element: +# a or y: year +# m: month +# j or d: day +# h: hour +# mn: minute +# s: second +# <example> banadd testname +1m-2mn1s-6y +# this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time. +# NOTE: If you modify the final date of a non-banished account, +# you fix the final date to (actual time +- adjustments) +# +# banset <account_name> yyyy/mm/dd [hh:mm:ss] +# Changes the final date of a banishment of an account. +# Default time: 23:59:59 +# banset <account_name> 0 +# Set a non-banished account (0 = unbanished). +# +# block <account name> +# Set state 5 (You have been blocked by the GM Team) to an account. +# Same command of state <account_name> 5. +# +# check <account_name> <password> +# Check the validity of a password for an account +# NOTE: Server will never sends back a password. +# It's the only method you have to know if a password is correct. +# The other method is to have a ('physical') access to the accounts file. +# +# create <account_name> <sex> <email> <password> +# Like the 'add' command, but with e-mail moreover. +# <example> create testname Male my@mail.com testpass +# +# del <account name> +# Remove an account. +# This order requires confirmation. After confirmation, the account is deleted. +# +# email <account_name> <email> +# Modify the e-mail of an account. +# +# getcount +# Give the number of players online on all char-servers. +# +# gm <account_name> [GM_level] +# Modify the GM level of an account. +# Default value remove GM level (GM level = 0). +# <example> gm testname 80 +# +# id <account name> +# Give the id of an account. +# +# info <account_id> +# Display complete information of an account. +# +# kami <message> +# Sends a broadcast message on all map-server (in yellow). +# kamib <message> +# Sends a broadcast message on all map-server (in blue). +# +# language <language> +# Change the language of displaying. +# +# list/ls [start_id [end_id]] +# Display a list of accounts. +# 'start_id', 'end_id': indicate end and start identifiers. +# Research by name is not possible with this command. +# <example> list 10 9999999 +# +# listBan/lsBan [start_id [end_id]] +# Like list/ls, but only for accounts with state or banished +# +# listGM/lsGM [start_id [end_id]] +# Like list/ls, but only for GM accounts +# +# listOK/lsOK [start_id [end_id]] +# Like list/ls, but only for accounts without state and not banished +# +# memo <account_name> <memo> +# Modify the memo of an account. +# 'memo': it can have until 253 characters (with spaces or not). +# +# name <account_id> +# Give the name of an account. +# +# passwd <account_name> <new_password> +# Change the password of an account. +# When new password is omitted, the input is done without displaying of the pressed keys. +# +# quit/end/exit +# End of the program of administration +# +# reloadGM +# Reload GM configuration file +# +# search <expression> +# Seek accounts. +# Displays the accounts whose names correspond. +# search -r/-e/--expr/--regex <expression> +# Seek accounts by regular expression. +# Displays the accounts whose names correspond. +# +# sex <account_name> <sex> +# Modify the sex of an account. +# <example> sex testname Male +# +# state <account_name> <new_state> <error_message_#7> +# Change the state of an account. +# 'new_state': state is the state of the packet 0x006a + 1. The possibilities are: +# 0 = Account ok 6 = Your Game's EXE file is not the latest version +# 1 = Unregistered ID 7 = You are Prohibited to log in until %s +# 2 = Incorrect Password 8 = Server is jammed due to over populated +# 3 = This ID is expired 9 = No MSG +# 4 = Rejected from Server 100 = This ID has been totally erased +# 5 = You have been blocked by the GM Team +# all other values are 'No MSG', then use state 9 please. +# 'error_message_#7': message of the code error 6 = Your are Prohibited to log in until %s (packet 0x006a) +# +# timeadd <account_name> <modifier> +# Adds or substracts time from the validity limit of an account. +# Modifier is done as follows: +# Adjustment value (-1, 1, +1, etc...) +# Modified element: +# a or y: year +# m: month +# j or d: day +# h: hour +# mn: minute +# s: second +# <example> timeadd testname +1m-2mn1s-6y +# this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time. +# NOTE: You can not modify a unlimited validity limit. +# If you want modify it, you want probably create a limited validity limit. +# So, at first, you must set the validity limit to a date/time. +# +# timeset <account_name> yyyy/mm/dd [hh:mm:ss] +# Changes the validity limit of an account. +# Default time: 23:59:59 +# timeset <account_name> 0 +# Gives an unlimited validity limit (0 = unlimited). +# +# unban/unbanish <account name> +# Unban an account. +# Same command of banset 0. +# +# unblock <account name> +# Set state 0 (Account ok) to an account. +# Same command of state <account_name> 0. +# +# version +# Display the version of the login-server. +# +# who <account name> +# Displays complete information of an account. +# +#------------------------------------------------------------------------- +# Possibilities to execute ladmin in command line by usage of the software with a parameter: +# ./ladmin --mode param1 ... +# +# --makesymlink -- Create the symbolic links for a use in shell +# --add <account_name> <sex> <password> -- Create an account with the default email (or -a) +# --ban yyyy/mm/dd hh:mm:ss <account_name> -- Change the final date of a banishment of an account (or -b) +# --banadd <account_name> <modifier> -- Add or substract time from the final date of a banishment of an account (or - ba) +# --banset <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the final date of a banishment of an account (or -bs) +# --banset <account_name> 0 -- Unbanish an account (or -bs) +# --block <account_name> -- Set state 5 to an account (or -bl) +# --check <account_name> <password> -- Check the validity of a password for an account (or -check) +# --create <account_name> <sex> <email> <password> -- Create an account with email (or -c) +# --del <account_name> -- Remove an account (or -d) +# --email <account_name> <email> -- Modify an email of an account (or -e) +# --getcount -- Give the number of players online on all char-servers (or -g) +# --gm <account_name> <GM_level> -- Change the GM level of an account (or -gm) +# --id <account_name> -- Give the id of an account (or -i) +# --info <account_id> -- Display complete information of an account (or -info) +# --kami <message> -- Sends a broadcast message on all map-server (in yellow). +# --kamib <message> -- Sends a broadcast message on all map-server (in blue). +# --language <language> -- Change the language of displaying (-lang). +# --list [First_id [Last_id]] -- Display a list of accounts (or -l) +# --listBan [start_id [end_id]] -- Display a list of accounts with state or banished (or -lBan) +# --listGM [First_id [Last_id]] -- Display a list of GM accounts (or -lGM) +# --listOK [start_id [end_id]] -- Display a list of accounts without state and not banished (or -lOK) +# --memo <account_name> <memo> -- Modify the memo of an account (or -e) +# --name <account_id> -- Give the name of an account (or -n) +# --passwd <account_name> <new_password> -- Change the password of an account (or -p) +# --reloadGM -- Reload GM configuration file (or -r) +# --search <expression> -- Seek accounts (or -s) +# --search -e/-r/--expr/--regex <expression> -- Seek accounts by REGEX (or -s) +# --sex <account_name> <sex> -- Change the sex of an account (or -sex) +# --state <account_name> <new_state> <error_message_#7> -- Change the state of an account (or -t) +# --timeadd <account_name> <modifier> -- Add or substract time from the validity limit of an account (or - ta) +# --timeset <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the validify limit of an account (or -ts) +# --timeset <account_name> 0 -- Give a unlimited validity limit (or -ts) +# --unban/unbanish <account_name> -- Unban an account (or -uba) +# --unblock <account_name> -- Set state 0 to an account (or -ubl) +# --version -- Display the version of the login-server (or -v) +# --who <account_name> -- Display complete information of an account (or -w) +# +# <example> ./ladmin --addaccount testname Male testpass +# +#------------------------------------------------------------------------- +# Possibilities to execute ladmin with symbolic links in Shell +# To create the symbolic links, execute ladmin with the '-- makesymlink' option. +# +# addaccount <account_name> <sex> <password> -- Create an account with the default email +# banaccount yyyy/mm/dd hh:mm:ss <account_name> -- Change the final date of a banishment of an account +# banaddaccount <account_name> <modifier> -- Add or substract time from the final date of a banishment of an account +# bansetaccount <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the final date of a banishment of an account +# bansetaccount <account_name> 0 -- Unbanish an account +# blockaccount <account_name> -- Set state 5 (blocked by the GM Team) to an account +# checkaccount <account_name> <password> -- Check the validity of a password for an account +# createaccount <account_name> <sex> <email> <password> -- Create an account with email +# delaccount <account_name> -- Remove an account +# emailaccount <account_name> <email> -- Modify an email of an account +# getcount -- Give the number of players online on all char-servers +# gmaccount <account_name> <GM_level> -- Change the GM level of an account +# idaccount <account_name> -- Give the id of an account +# infoaccount <account_id> -- Display complete information of an account +# kami <message> -- Sends a broadcast message on all map-server (in yellow). +# kamib <message> -- Sends a broadcast message on all map-server (in blue). +# ladminlanguage <language> -- Change the language of displaying. +# listaccount [First_id [Last_id]] -- Display a list of accounts +# listBanaccount [start_id [end_id]] -- Display a list of accounts with state or banished +# listGMaccount [First_id [Last_id]] -- Display a list of GM accounts +# listOKaccount [start_id [end_id]] -- Display a list of accounts without state and not banished +# loginserverversion -- Display the version of the login-server +# memoaccount <account_name> <memo> -- Modify the memo of an account +# nameaccount <account_id> -- Give the name of an account +# passwdaccount <account_name> <new_password> -- Change the password of an account +# reloadGM -- Reload GM configuration file +# searchaccount <expression> -- Seek accounts +# searchaccount -e/-r/--expr/--regex <expression> -- Seek accounts by REGEX +# sexaccount <account_name> <sex> -- Change the sex of an account (or -sex) +# stateaccount <account_name> <new_state> <error_message_#7> -- Change the state of an account +# timeaddaccount <account_name> <modifier> -- Add or substract time from the validity limit of an account +# timesetaccount <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the validify limit of an account +# timesetaccount <account_name> 0 -- Give a unlimited validity limit +# unbanaccount <account_name> -- Unban an account +# unblockaccount <account_name> -- Set state 0 (Account ok) to an account +# whoaccount <account_name> -- Display complete information of an account +# <exemple> ./addaccount testname Male testpass +# +#------------------------------------------------------------------------- +# About the encoding: +# +# The Digest::MD5 module is necessary to use the encrypted password system. +# When the software cannot found the Digest::MD5 module, +# encoding is automatically disabled ($passenc=0), which allows +# to use this program in any cases. +# +#------------------------------------------------------------------------- +# How to use ladmin with UNIX: +# +# You excecute ladmin as a standard command. +# <Example of preparation to have an access to ladmin> +# $ mv ladmin ladmin_org +# $ nkf -eLu ladmin_org > ladmin +# $ chmod 700 ladmin +# <Example to start directly ladmin> +# $ perl ladmin +# +########################################################################## + + +use strict; +use IO::Socket; +use Term::ReadLine; +eval { use POSIX qw(:termios_h); }; +eval { use Digest::MD5 qw(md5); } if $passenc; +$passenc = 0 if($@); + +my($ver) = "1.00"; + +# Start of termios +my($termios, $orgterml, $termlecho, $termlnoecho) = (); +eval{ + $termios = POSIX::Termios->new(); + $termios->getattr(fileno(STDIN)); + $orgterml = $termios->getlflag(); + $termlecho = ECHO | ECHOK | ICANON; + $termlnoecho = $orgterml & ~$termlecho; +}; + +# Modification of termios for the displaying of passwords (no displays for pressed keys) +sub cbreak() { + if ($termios) { + $termios->setlflag($termlnoecho); + $termios->setcc(VTIME, 1); + $termios->setattr(fileno(STDIN), TCSANOW); + } +} +# Modification of termios to return at the normal displaying (after input of the passwords) +sub cooked() { + if ($termios) { + $termios->setlflag($orgterml); + $termios->setcc(VTIME,0); + $termios->setattr(fileno(STDIN),TCSANOW); + } +} +END{ cooked() } + +if ($defaultlanguage eq "F") { + print "Outil d'administration à distance de eAthena V.$ver\n"; +} else { + print "EAthena login-server administration tool V.$ver\n"; +} + +# Creation of the symbolic links for call of the program in line command of the shell +if ($ARGV[0] eq "--makesymlink") { + symlink $0, "loginserverversion"; + symlink $0, "addaccount"; + symlink $0, "banaccount"; + symlink $0, "banaddaccount"; + symlink $0, "bansetaccount"; + symlink $0, "blockaccount"; + symlink $0, "checkaccount"; + symlink $0, "createaccount"; + symlink $0, "delaccount"; + symlink $0, "emailaccount"; + symlink $0, "getcount"; + symlink $0, "gmaccount"; + symlink $0, "idaccount"; + symlink $0, "infoaccount"; + symlink $0, "kami"; + symlink $0, "kamib"; + symlink $0, "ladminlanguage"; + symlink $0, "listaccount"; + symlink $0, "listBanaccount"; + symlink $0, "listGMaccount"; + symlink $0, "listOKaccount"; + symlink $0, "memoaccount"; + symlink $0, "nameaccount"; + symlink $0, "passwdaccount"; + symlink $0, "reloadGM"; + symlink $0, "searchaccount"; + symlink $0, "sexaccount"; + symlink $0, "stateaccount"; + symlink $0, "timeaddaccount"; + symlink $0, "timesetaccount"; + symlink $0, "unbanaccount"; + symlink $0, "unblockaccount"; + symlink $0, "whoaccount"; + if ($defaultlanguage eq "F") { + print "Liens symbliques créés.\n"; + } else { + print "Symbolic links created.\n"; + } + exit(0); +} + +# Connection to the login-server +my($so,$er) = (); +eval{ + $so = IO::Socket::INET->new( + PeerAddr=> $loginserverip, + PeerPort=> $loginserverport, +# Proto => "tcp", + Timeout => $connecttimeout) or $er = 1; +}; +if ($er || $@) { + if ($defaultlanguage eq "F") { + print "\nImpossible de se connecter au serveur de login [${loginserverip}:$loginserverport] !\n"; + } else { + print "\nImpossible to have a connection with the login-server [${loginserverip}:$loginserverport] !\n"; + } + print "$!\n"; # Displaying of the error + exit(2); +} + +# Sending the administration password +if ($passenc == 0) { + print $so pack("v2a24",0x7918,0,$loginserveradminpassword); + $so->flush(); +} else { + print $so pack("v",0x791a); + $so->flush(); + my($buf) = readso(4); + if (unpack("v",$buf) != 0x01dc) { + if ($defaultlanguage eq "F") { + print "Erreur au login (échec de la création de la clef md5).\n"; + } else { + print "Error at login (failure of the md5 key creation).\n"; + } + } + $buf = readso(unpack("x2v",$buf)-4); + my($md5bin) = md5(($passenc == 1) ? $buf.$loginserveradminpassword : $loginserveradminpassword.$buf); + print $so pack("v2a16",0x7918,$passenc,$md5bin); + $so->flush(); +} + +# Waiting of the server reply +my($buf) = readso(3); + +if (unpack("v",$buf) != 0x7919 || unpack("x2c",$buf) != 0) { + if ($defaultlanguage eq "F") { + print "Erreur de login:\n"; + print " - mot de passe incorrect,\n"; + print " - système d'administration non activé, ou\n"; + print " - IP non autorisée.\n"; + } else { + print "Error at login:\n"; + print " - incorrect password,\n"; + print " - administration system not activated, or\n"; + print " - unauthorised IP.\n"; + } + quit(); + exit(4); +} + +if ($defaultlanguage eq "F") { + print "Connexion établie.\n"; +} else { + print "Established connection.\n"; +} + +#------------------------------------------------------------------------- +# Here are checked the command lines with arguments and symbolic links (no prompt) + +if ($0 =~ /addaccount$/ || + (($ARGV[0] eq "-a" || $ARGV[0] eq "--add") && ((shift @ARGV), 1))) { + my($r) = addaccount($ARGV[0], $ARGV[1], $ARGV[2]); + quit(); + exit($r); +} elsif ($0 =~ /banaccount$/ || $0 =~ /banishaccount$/ || + (($ARGV[0] eq "-b" || $ARGV[0] eq "--ban" || $ARGV[0] eq "--banish") && ((shift @ARGV), 1))) { + my($r) = bansetaccount($ARGV[1], $ARGV[2], $ARGV[0]); + quit(); + exit($r); +} elsif ($0 =~ /banaddaccount$/ || + (($ARGV[0] eq "-ba" || $ARGV[0] eq "--banadd") && ((shift @ARGV), 1))) { + my($r) = banaddaccount($ARGV[0], $ARGV[1]); + quit(); + exit($r); +} elsif ($0 =~ /bansetaccount$/ || + (($ARGV[0] eq "-bs" || $ARGV[0] eq "--banset") && ((shift @ARGV), 1))) { + my($r) = bansetaccount($ARGV[0], $ARGV[1], $ARGV[2]); + quit(); + exit($r); +} elsif ($0 =~ /blockaccount$/ || + (($ARGV[0] eq "-bl" || $ARGV[0] eq "--block") && ((shift @ARGV), 1))) { + my($r) = changestate($ARGV[0], 5, ""); + quit(); + exit($r); +} elsif ($0 =~ /checkaccount$/ || + (($ARGV[0] eq "-check" || $ARGV[0] eq "--check") && ((shift @ARGV), 1))) { + my($r) = checkaccount($ARGV[0], $ARGV[1]); + quit(); + exit($r); +} elsif ($0 =~ /createaccount$/ || + (($ARGV[0] eq "-c" || $ARGV[0] eq "--create") && ((shift @ARGV), 1))) { + my($r) = createaccount($ARGV[0], $ARGV[1], $ARGV[2], $ARGV[3]); + quit(); + exit($r); +} elsif ($0 =~ /delaccount$/ || + (($ARGV[0] eq "-d" || $ARGV[0] eq "--del") && ((shift @ARGV), 1))) { + my($r) = delaccount($ARGV[0]); + quit(); + exit($r); +} elsif ($0 =~ /emailaccount$/ || + (($ARGV[0] eq "-e" || $ARGV[0] eq "--email") && ((shift @ARGV), 1))) { + my($r) = changeemail($ARGV[0], $ARGV[1]); + quit(); + exit($r); +} elsif ($0 =~ /getcount$/ || + (($ARGV[0] eq "-g" || $ARGV[0] eq "--getcount") && ((shift @ARGV), 1))) { + my($r) = getlogincount(); + quit(); + exit($r); +} elsif ($0 =~ /gmaccount$/ || + (($ARGV[0] eq "-gm" || $ARGV[0] eq "--gm") && ((shift @ARGV), 1))) { + my($r) = changegmlevel($ARGV[0], $ARGV[1]); + quit(); + exit($r); +} elsif ($0 =~ /id$/ || + (($ARGV[0] eq "-i" || $ARGV[0] eq "--id") && ((shift @ARGV), 1))) { + my($r) = idaccount($ARGV[0]); + quit(); + exit($r); +} elsif ($0 =~ /infoaccount$/ || + (($ARGV[0] eq "-info" || $ARGV[0] eq "--info") && ((shift @ARGV), 1))) { + my($r) = infoaccount($ARGV[0]); + quit(); + exit($r); +} elsif ($0 =~ /kami$/ || + (($ARGV[0] eq "-kami" || $ARGV[0] eq "--kami") && ((shift @ARGV), 1))) { + my($r) = sendbroadcast(0, $ARGV[0]); + quit(); + exit($r); +} elsif ($0 =~ /kamib$/ || + (($ARGV[0] eq "-kamib" || $ARGV[0] eq "--kamib") && ((shift @ARGV), 1))) { + my($r) = sendbroadcast(0x10, $ARGV[0]); + quit(); + exit($r); +} elsif ($0 =~ /ladminlanguage$/ || + (($ARGV[0] eq "-lang" || $ARGV[0] eq "--language") && ((shift @ARGV), 1))) { + my($r) = changelanguage($ARGV[0]); + quit(); + exit($r); +} elsif ($0 =~ /listaccount$/ || + (($ARGV[0] eq "-l" || $ARGV[0] eq "--list") && ((shift @ARGV), 1))) { + my($r) = listaccount(int($ARGV[0]), int($ARGV[1]), 0); # 0: to list all + quit(); + exit($r); +} elsif ($0 =~ /listBanaccount$/ || + (($ARGV[0] eq "-lBan" || $ARGV[0] eq "--listBan") && ((shift @ARGV), 1))) { + my($r) = listaccount(int($ARGV[0]), int($ARGV[1]), 3); # 3: to list only accounts with state or banished + quit(); + exit($r); +} elsif ($0 =~ /listGMaccount$/ || + (($ARGV[0] eq "-lGM" || $ARGV[0] eq "--listGM") && ((shift @ARGV), 1))) { + my($r) = listaccount(int($ARGV[0]), int($ARGV[1]), 1); # 1: to list only GM + quit(); + exit($r); +} elsif ($0 =~ /listOKaccount$/ || + (($ARGV[0] eq "-lOK" || $ARGV[0] eq "--listOK") && ((shift @ARGV), 1))) { + my($r) = listaccount(int($ARGV[0]), int($ARGV[1]), 4); # 4: to list only accounts without state and not banished + quit(); + exit($r); +} elsif ($0 =~ /loginserverversion$/ || + (($ARGV[0] eq "-v" || $ARGV[0] eq "--version") && ((shift @ARGV), 1))) { + my($r) = checkloginversion(); + quit(); + exit($r); +} elsif ($0 =~ /memoaccount$/ || + (($ARGV[0] eq "-m" || $ARGV[0] eq "--memo") && ((shift @ARGV), 1))) { + my($r) = changememo($ARGV[0], $ARGV[1]); + quit(); + exit($r); +} elsif ($0 =~ /nameaccount$/ || + (($ARGV[0] eq "-n" || $ARGV[0] eq "--name") && ((shift @ARGV), 1))) { + my($r) = nameaccount(int($ARGV[0])); + quit(); + exit($r); +} elsif ($0 =~ /passwdaccount$/ || + (($ARGV[0] eq "-p" || $ARGV[0] eq "--passwd") && ((shift @ARGV), 1))) { + my($r) = changepasswd($ARGV[0], $ARGV[1]); + quit(); + exit($r); +} elsif ($0 =~ /reloadGM$/ || + (($ARGV[0] eq "-r" || $ARGV[0] eq "--reloadGM") && ((shift @ARGV), 1))) { + my($r) = reloadGM(); + quit(); + exit($r); +} elsif ($0 =~ /searchaccount$/ || + (($ARGV[0] eq "-s" || $ARGV[0] eq "--search") && ((shift @ARGV), 1))) { + my($r) = searchaccount($ARGV[0], $ARGV[1]); + quit(); + exit($r); +} elsif ($0 =~ /sexaccount$/ || + (($ARGV[0] eq "-sex" || $ARGV[0] eq "--sex") && ((shift @ARGV), 1))) { + my($r) = changesex($ARGV[0], $ARGV[1]); + quit(); + exit($r); +} elsif ($0 =~ /stateaccount$/ || + (($ARGV[0] eq "-t" || $ARGV[0] eq "--state") && ((shift @ARGV), 1))) { + my($r) = changestate($ARGV[0], $ARGV[1], $ARGV[2]); + quit(); + exit($r); +} elsif ($0 =~ /timeaddaccount$/ || + (($ARGV[0] eq "-ta" || $ARGV[0] eq "--timeadd") && ((shift @ARGV), 1))) { + my($r) = timeaddaccount($ARGV[0], $ARGV[1]); + quit(); + exit($r); +} elsif ($0 =~ /timesetaccount$/ || + (($ARGV[0] eq "-ts" || $ARGV[0] eq "--timeset") && ((shift @ARGV), 1))) { + my($r) = timesetaccount($ARGV[0], $ARGV[1], $ARGV[2]); + quit(); + exit($r); +} elsif ($0 =~ /unbanaccount$/ || $0 =~ /unbanishaccount$/ || + (($ARGV[0] eq "-uba" || $ARGV[0] eq "--unban" || $ARGV[0] eq "--unbanish") && ((shift @ARGV), 1))) { + my($r) = bansetaccount($ARGV[0], 0, ""); + quit(); + exit($r); +} elsif ($0 =~ /unblockaccount$/ || + (($ARGV[0] eq "-ubl" || $ARGV[0] eq "--unblock") && ((shift @ARGV), 1))) { + my($r) = changestate($ARGV[0], 0, ""); + quit(); + exit($r); +} elsif ($0 =~ /whoaccount$/ || + (($ARGV[0] eq "-w" || $ARGV[0] eq "--who") && ((shift @ARGV), 1))) { + my($r) = whoaccount($ARGV[0]); + quit(); + exit($r); +} + +#------------------------------------------------------------------------- +if ($defaultlanguage eq "F") { + print "Lecture de la version du serveur de login...\n"; +} else { + print "Reading of the version of the login-server...\n"; +} +checkloginversion(); + +# Set the prompt line +my($term) = new Term::ReadLine "ladmin"; + +# Here begin the infinite loop to read prompts +while(1) { + # Displaying of the prompt + print "\n"; + if ($defaultlanguage eq "F") { + printf "\033[32mPour afficher les commandes, tapez 'Entrée'.\033[0m\n"; + } else { + printf "\033[32mTo list the commands, type 'enter'.\033[0m\n"; + } + my($cmd) = $term->readline("ladmin> "); + # split and recovery of the input + chomp $cmd; # remove cariage return + $cmd =~ s/\x1b\[\d*\w//g; # remove (esc)[(number)(1alpha) = screen control sequence + $cmd =~ s/[\x00-\x1f]//g; # remove control char + my($command, $parameters) = split /\s+/,$cmd,2; # extract command and parameters + $command = lc($command); # command in lowercase + my(@paramlist) = split /\s+/,$parameters; # get list of parameters + + if ($command eq "?" || $command eq "") { + $command = "aide" if ($defaultlanguage eq "F"); + $command = "help" if ($defaultlanguage ne "F"); + } + + # Analyse of the command + eval { +# help + if ("aide" =~ /^\Q$command/ && $command ne "a") { # check 1 letter command: 'aide' or 'add'? + displayhelp("aide", $paramlist[0]); + } elsif ("help" =~ /^\Q$command/) { + displayhelp("help", $paramlist[0]); + +# general commands + } elsif ("add" =~ /^\Q$command/ && $command ne "a") { # check 1 letter command: 'aide' or 'add'? + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)\s+(.*)/)) { + addaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> <sex> <password> + } elsif (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) { + addaccount($paramlist[0], $paramlist[1], ""); # <account_name> <sex> <password> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)\s+(.*)/)) { + addaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> <sex> <password> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) { + addaccount($paramlist[0], $paramlist[1], ""); # <account_name> <sex> <password> + } else { + @paramlist = split /\s+/,$parameters; + addaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> <sex> <password> + } + + } elsif ($command eq "ban" || ("banish" =~ /^\Q$command/ && length($command) >= 4)) { + if (@paramlist = ($parameters =~ m/^(\S+)\s+(\S+)\s+"(.*)"/)) { # yyyy/mm/dd hh:mm:ss <account_name> + bansetaccount($paramlist[2], $paramlist[0], $paramlist[1]); # <account_name> yyyy/mm/dd [hh:mm:ss] + } elsif (@paramlist = ($parameters =~ m/^(\S+)\s+(\S+)\s+'(.*)'/)) { # yyyy/mm/dd hh:mm:ss <account_name> + bansetaccount($paramlist[2], $paramlist[0], $paramlist[1]); # <account_name> yyyy/mm/dd [hh:mm:ss] + } else { + @paramlist = split /\s+/,$parameters,3; # yyyy/mm/dd hh:mm:ss <account_name> + bansetaccount($paramlist[2], $paramlist[0], $paramlist[1]); # <account_name> yyyy/mm/dd [hh:mm:ss] + } + + } elsif (("banadd" =~ /^\Q$command/ || $command eq "ba") && $command ne "b") { # check 1 letter command: 'ba' or 'bs'? + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) { + banaddaccount($paramlist[0], $paramlist[1]); # <account_name> <modifier> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) { + banaddaccount($paramlist[0], $paramlist[1]); # <account_name> <modifier> + } else { + @paramlist = split /\s+/,$parameters; + banaddaccount($paramlist[0], $paramlist[1]); # <account_name> <modifier> + } + + } elsif (("banset" =~ /^\Q$command/ || $command eq "bs") && $command ne "b") { # check 1 letter command: 'ba' or 'bs'? + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)\s+(\S+)/)) { + bansetaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> yyyy/mm/dd [hh:mm:ss] + } elsif (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) { + bansetaccount($paramlist[0], $paramlist[1], "23:59:59"); # <account_name> yyyy/mm/dd [hh:mm:ss] + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)\s+(\S+)/)) { + bansetaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> yyyy/mm/dd [hh:mm:ss] + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) { + bansetaccount($paramlist[0], $paramlist[1], "23:59:59"); # <account_name> yyyy/mm/dd [hh:mm:ss] + } else { + @paramlist = split /\s+/,$parameters; + bansetaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> yyyy/mm/dd [hh:mm:ss] + } + + } elsif ("block" =~ /^\Q$command/ && length($command) >= 2) { + if (@paramlist = ($parameters =~ m/^"(.*)"/)) { + changestate($paramlist[0], 5, ""); # <account_name> <new_state> <error_message_#7> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) { + changestate($paramlist[0], 5, ""); # <account_name> <new_state> <error_message_#7> + } else { + @paramlist = split /\s+/,$parameters,1; + changestate($paramlist[0], 5, ""); # <account_name> <new_state> <error_message_#7> + } + + } elsif ("check" =~ /^\Q$command/ && $command ne "c") { # check 1 letter command: 'check' or 'create'? + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(.*)/)) { + checkaccount($paramlist[0], $paramlist[1]); # <account_name> <password> + } elsif (@paramlist = ($parameters =~ m/^"(.*)"/)) { + checkaccount($paramlist[0], ""); # <account_name> <password> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(.*)/)) { + checkaccount($paramlist[0], $paramlist[1]); # <account_name> <password> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) { + checkaccount($paramlist[0], ""); # <account_name> <password> + } else { + @paramlist = split /\s+/,$parameters; + checkaccount($paramlist[0], $paramlist[1]); # <account_name> <password> + } + + } elsif ("create" =~ /^\Q$command/ && $command ne "c") { # check 1 letter command: 'check' or 'create'? + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)\s+(\S+)\s+(.*)/)) { + createaccount($paramlist[0], $paramlist[1], $paramlist[2], $paramlist[3]); # <account_name> <sex> <email> <password> + } elsif (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)\s+(\S+)/)) { + createaccount($paramlist[0], $paramlist[1], $paramlist[2], ""); # <account_name> <sex> <email> <password> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)\s+(\S+)\s+(.*)/)) { + createaccount($paramlist[0], $paramlist[1], $paramlist[2], $paramlist[3]); # <account_name> <sex> <email> <password> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)\s+(\S+)/)) { + createaccount($paramlist[0], $paramlist[1], $paramlist[2], ""); # <account_name> <sex> <email> <password> + } else { + @paramlist = split /\s+/,$parameters; + createaccount($paramlist[0], $paramlist[1], $paramlist[2], $paramlist[3]); # <account_name> <sex> <email> <password> + } + + } elsif ("del" =~ /^\Q$command/ || "delete" =~ /^\Q$command/) { + if (@paramlist = ($parameters =~ m/^"(.*)"/)) { + delaccount($paramlist[0]); # <account_name> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) { + delaccount($paramlist[0]); # <account_name> + } else { + @paramlist = split /\s+/,$parameters,1; + delaccount($paramlist[0]); # <account_name> + } + + } elsif ("email" =~ /^\Q$command/ && $command ne "e") { # check 1 letter command: 'email', 'end' or 'exit'? + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) { + changeemail($paramlist[0], $paramlist[1]); # <account_name> <email> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) { + changeemail($paramlist[0], $paramlist[1]); # <account_name> <email> + } else { + @paramlist = split /\s+/,$parameters; + changeemail($paramlist[0], $paramlist[1]); # <account_name> <email> + } + + } elsif ("getcount" =~ /^\Q$command/ && $command ne "g") { # check 1 letter command: 'getcount' or 'gm'? + getlogincount(); + + } elsif ("gm" =~ /^\Q$command/ && $command ne "g") { # check 1 letter command: 'getcount' or 'gm'? + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) { + changegmlevel($paramlist[0], int($paramlist[1])); # <account_name> <GM_level> + } elsif (@paramlist = ($parameters =~ m/^"(.*)"/)) { + changegmlevel($paramlist[0], 0); # <account_name> <GM_level> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) { + changegmlevel($paramlist[0], int($paramlist[1])); # <account_name> <GM_level> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) { + changegmlevel($paramlist[0], 0); # <account_name> <GM_level> + } else { + @paramlist = split /\s+/,$parameters; + changegmlevel($paramlist[0], int($paramlist[1])); # <account_name> <GM_level> + } + + } elsif ("id" =~ /^\Q$command/ && $command ne "i") { # check 1 letter command: 'id' or 'info'? + if (@paramlist = ($parameters =~ m/^"(.*)"/)) { + idaccount($paramlist[0]); # <account_name> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) { + idaccount($paramlist[0]); # <account_name> + } else { + @paramlist = split /\s+/,$parameters,1; + idaccount($paramlist[0]); # <account_name> + } + + } elsif ("info" =~ /^\Q$command/ && $command ne "i") { # check 1 letter command: 'id' or 'info'? + infoaccount(int($paramlist[0])); # <account_id> + + } elsif ($command eq "kami") { # check all letters command: 'kami' or 'kamib'? + @paramlist = split /\s+/,$parameters,1; + sendbroadcast(0, $paramlist[0]); # <type> <message> + + } elsif ($command eq "kamib") { # check all letters command: 'kami' or 'kamib'? + @paramlist = split /\s+/,$parameters,1; + sendbroadcast(0x10, $paramlist[0]); # <type> <message> + + } elsif ("language" =~ /^\Q$command/ && $command ne "l") { # check 1 letter command: 'list' or 'language'? + changelanguage($paramlist[0]); # <language> + + } elsif (("list" =~ /^\Q$command/ || $command eq "ls") && $command ne "l") { # check 1 letter command: 'list' or 'language'? + listaccount(int($paramlist[0]), int($paramlist[1]), 0); # [start_id [end_id]] 0: to list all + + } elsif (("listban" =~ /^\Q$command/ || $command eq "lsban") && $command ne "l") { # need to specificaly write Ban to have this list # check 1 letter command: 'list' or 'language'? + listaccount(int($paramlist[0]), int($paramlist[1]), 3); # [start_id [end_id]] 3: to list only accounts with state or banished + + } elsif (("listgm" =~ /^\Q$command/ || $command eq "lsgm") && $command ne "l") { # need to specificaly write GM to have this list # check 1 letter command: 'list' or 'language'? + listaccount(int($paramlist[0]), int($paramlist[1]), 1); # [start_id [end_id]] 1: to list only GM + + } elsif (("listok" =~ /^\Q$command/ || $command eq "lsok") && $command ne "l") { # need to specificaly write OK to have this list # check 1 letter command: 'list' or 'language'? + listaccount(int($paramlist[0]), int($paramlist[1]), 4); # [start_id [end_id]] 4: to list only accounts without state and not banished + + } elsif ("memo" =~ /^\Q$command/) { + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(.*)/)) { + changememo($paramlist[0], $paramlist[1]); # <account_name> <memo> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(.*)/)) { + changememo($paramlist[0], $paramlist[1]); # <account_name> <memo> + } else { + @paramlist = split /\s+/,$parameters,2; + changememo($paramlist[0], $paramlist[1]); # <account_name> <memo> + } + + } elsif ("name" =~ /^\Q$command/) { + nameaccount(int($paramlist[0])); # <account_id> + + } elsif ("passwd" =~ /^\Q$command/ || "password" =~ /^\Q$command/) { + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(.*)/)) { + changepasswd($paramlist[0], $paramlist[1]); # <account_name> <new_password> + } elsif (@paramlist = ($parameters =~ m/^"(.*)"/)) { + changepasswd($paramlist[0], ""); # <account_name> <new_password> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(.*)/)) { + changepasswd($paramlist[0], $paramlist[1]); # <account_name> <new_password> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) { + changepasswd($paramlist[0], ""); # <account_name> <new_password> + } else { + @paramlist = split /\s+/,$parameters,2; + changepasswd($paramlist[0], $paramlist[1]); # <account_name> <new_password> + } + + } elsif ("reloadgm" =~ /^\Q$command/) { + reloadGM(); + + } elsif ("search" =~ /^\Q$command/ && $command ne "s" && # check 1 letter command: 'search', 'state' or 'sex'? + $command ne "se") { # check 2 letters command: 'search' or 'sex'? + if (@paramlist = ($parameters =~ m/^(-{1,2}[re]\S*)\s+(.*)/)) { + searchaccount($paramlist[0], $paramlist[1]); # -r/-e/--expr/--regex <expression> | <expression> + } else { + @paramlist = split /\s+/,$parameters,1; + searchaccount($paramlist[0], ""); # -r/-e/--expr/--regex <expression> | <expression> + } + + } elsif ("sex" =~ /^\Q$command/ && $command ne "s" && # check 1 letter command: 'search', 'state' or 'sex'? + $command ne "se") { # check 2 letters command: 'search' or 'sex'? + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) { + changesex($paramlist[0], $paramlist[1]); # <account_name> <sex> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) { + changesex($paramlist[0], $paramlist[1]); # <account_name> <sex> + } else { + @paramlist = split /\s+/,$parameters; + changesex($paramlist[0], $paramlist[1]); # <account_name> <sex> + } + + } elsif ("state" =~ /^\Q$command/ && $command ne "s") { # check 1 letter command: 'search', 'state' or 'sex'? + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\d+)\s+(.*)/)) { + changestate($paramlist[0], int($paramlist[1]), $paramlist[2]); # <account_name> <new_state> <error_message_#7> + } elsif (@paramlist = ($parameters =~ m/^"(.*)"\s+(\d+)/)) { + changestate($paramlist[0], int($paramlist[1]), ""); # <account_name> <new_state> <error_message_#7> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\d+)\s+(.*)/)) { + changestate($paramlist[0], int($paramlist[1]), $paramlist[2]); # <account_name> <new_state> <error_message_#7> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\d+)/)) { + changestate($paramlist[0], int($paramlist[1]), ""); # <account_name> <new_state> <error_message_#7> + } else { + @paramlist = split /\s+/,$parameters,3; + changestate($paramlist[0], int($paramlist[1]), $paramlist[2]); # <account_name> <new_state> <error_message_#7> + } + + } elsif (("timeadd" =~ /^\Q$command/ || $command eq "ta") && $command ne "t") { # check 1 letter command: 'ta' or 'ts'? + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) { + timeaddaccount($paramlist[0], $paramlist[1]); # <account_name> <modifier> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) { + timeaddaccount($paramlist[0], $paramlist[1]); # <account_name> <modifier> + } else { + @paramlist = split /\s+/,$parameters; + timeaddaccount($paramlist[0], $paramlist[1]); # <account_name> <modifier> + } + + } elsif (("timeset" =~ /^\Q$command/ || $command eq "ts") && $command ne "t") { # check 1 letter command: 'ta' or 'ts'? + if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)\s+(\S+)/)) { + timesetaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> yyyy/mm/dd [hh:mm:ss] + } elsif (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) { + timesetaccount($paramlist[0], $paramlist[1], "23:59:59"); # <account_name> yyyy/mm/dd [hh:mm:ss] + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)\s+(\S+)/)) { + timesetaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> yyyy/mm/dd [hh:mm:ss] + } elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) { + timesetaccount($paramlist[0], $paramlist[1], "23:59:59"); # <account_name> yyyy/mm/dd [hh:mm:ss] + } else { + @paramlist = split /\s+/,$parameters; + timesetaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> yyyy/mm/dd [hh:mm:ss] + } + + } elsif ($command eq "unban" || ("unbanish" =~ /^\Q$command/ && length($command) >= 4)) { + if (@paramlist = ($parameters =~ m/^"(.*)"/)) { + bansetaccount($paramlist[0], 0, ""); # <account_name> yyyy/mm/dd [hh:mm:ss] + } elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) { + bansetaccount($paramlist[0], 0, ""); # <account_name> yyyy/mm/dd [hh:mm:ss] + } else { + @paramlist = split /\s+/,$parameters,1; + bansetaccount($paramlist[0], 0, ""); # <account_name> yyyy/mm/dd [hh:mm:ss] + } + + } elsif ("unblock" =~ /^\Q$command/ && length($command) >= 4) { + if (@paramlist = ($parameters =~ m/^"(.*)"/)) { + changestate($paramlist[0], 0, ""); # <account_name> <new_state> <error_message_#7> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) { + changestate($paramlist[0], 0, ""); # <account_name> <new_state> <error_message_#7> + } else { + @paramlist = split /\s+/,$parameters,1; + changestate($paramlist[0], 0, ""); # <account_name> <new_state> <error_message_#7> + } + + } elsif ("version" =~ /^\Q$command/) { + checkloginversion(); + + } elsif ("who" =~ /^\Q$command/) { + if (@paramlist = ($parameters =~ m/^"(.*)"/)) { + whoaccount($paramlist[0]); # <account_name> + } elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) { + whoaccount($paramlist[0]); # <account_name> + } else { + @paramlist = split /\s+/,$parameters,1; + whoaccount($paramlist[0]); # <account_name> + } + +# quit + } elsif ("quit" =~ /^\Q$command/ || + (("end" =~ /^\Q$command/ || "exit" =~ /^\Q$command/) && $command ne "e")) { # check 1 letter command: 'email', 'end' or 'exit'? + last; + +# unknown command + } elsif ($command) { + if ($defaultlanguage eq "F") { + print "Commande inconnue [".$command."]\n"; + } else { + print "Unknown command [".$command."]\n"; + } + } +# $term->addhistory($cmd) if $command; + }; + if ($@) { + if ($defaultlanguage eq "F") { + print "Erreur [".$command."]\n$@"; + } else { + print "Error [".$command."]\n$@"; + } + } +}; + +# End of the software +quit(); + +if ($defaultlanguage eq "F") { + print "Au revoir.\n"; +} else { + print "Bye.\n"; +} +exit(0); + +#-------------------------------------------------------------------------- + +# Sub-function: Displaying of the version of the login-server +sub checkloginversion() { + print $so pack("v",30000); # 0x7530 + $so->flush(); + $buf = readso(10); + # Analyse du Packet + my($ret, $maver, $miver, $rev, $dev, $mod, $type, $mdver) = unpack("vc6v", $buf); + if ($ret != 30001) { #0x7531 + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + exit(6); + } + + print " Login-Server [$loginserverip:$loginserverport]\n"; + printf " eAthena version %s-%d.%d", ("stable", "dev")[$dev], $maver, $miver; + printf " revision %d", $rev if $rev; + printf "%s%d.\n", ("", "-mod")[$mod], $mdver; + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Displaying of the help +sub displayhelp() { + my($help, $receivedcommand) = @_; + + my($command) = lc($receivedcommand); # command in lowercase + + if ($command eq "") { + $command = "not a command"; # any value that is not a command + } + + if ($command eq "?") { + $command = "aide" if ($defaultlanguage eq "F"); + $command = "help" if ($defaultlanguage ne "F"); + } + + if ($help eq "aide") { + if ("aide" =~ /^\Q$command/ && $command ne "a") { # check 1 letter command: 'aide' or 'add'? + printf "aide/help/?\n"; + printf " Affiche la description des commandes\n"; + printf "aide/help/? [commande]\n"; + printf " Affiche la description de la commande specifiée\n"; + } elsif ("help" =~ /^\Q$command/) { + printf "aide/help/?\n"; + printf " Display the description of the commands\n"; + printf "aide/help/? [command]\n"; + printf " Display the description of the specified command\n"; + } elsif ("add" =~ /^\Q$command/ && $command ne "a") { # check 1 letter command: 'aide' or 'add'? + printf "add <nomcompte> <sexe> <motdepasse>\n"; + printf " Crée un compte avec l'email par défaut (a\@a.com).\n"; + printf " Concernant le sexe, seule la première lettre compte (F ou M).\n"; + printf " L'e-mail est a\@a.com (e-mail par défaut). C'est comme n'avoir aucun e-mail.\n"; + printf " Lorsque motdepasse est omis, la saisie se fait sans que la frappe se voit.\n"; + printf " <exemple> add testname Male testpass\n"; + } elsif ($command eq "ban" || ("banish" =~ /^\Q$command/ && length($command) >= 4)) { + printf "ban/banish aaaa/mm/jj hh:mm:ss <nomcompte>\n"; + printf " Change la date de fin de bannissement d'un compte.\n"; + printf " La différence avec banset est la position du nom du compte.\n"; + } elsif (("banadd" =~ /^\Q$command/ || $command eq "ba") && $command ne "b") { # check 1 letter command: 'ba' or 'bs'? + printf "banadd <nomcompte> <Modificateur>\n"; + printf " Ajoute ou soustrait du temps à la date de banissement d'un compte.\n"; + printf " Les modificateurs sont construits comme suit:\n"; + printf " Valeur d'ajustement (-1, 1, +1, etc...)\n"; + printf " Elément modifié:\n"; + printf " a ou y: année\n"; + printf " m: mois\n"; + printf " j ou d: jour\n"; + printf " h: heure\n"; + printf " mn: minute\n"; + printf " s: seconde\n"; + printf " <exemple> banadd testname +1m-2mn1s-6a\n"; + printf " Cette exemple ajoute 1 mois et une seconde, et soustrait 2 minutes\n"; + printf " et 6 ans dans le même temps.\n"; + printf "NOTE: Si vous modifez la date de banissement d'un compte non bani,\n"; + printf " vous indiquez comme date (le moment actuel +- les ajustements)\n"; + } elsif (("banset" =~ /^\Q$command/ || $command eq "bs") && $command ne "b") { # check 1 letter command: 'ba' or 'bs'? + printf "banset <nomcompte> aaaa/mm/jj [hh:mm:ss]\n"; + printf " Change la date de fin de bannissement d'un compte.\n"; + printf " Heure par défaut: 23:59:59\n"; + printf "banset <nomcompte> 0\n"; + printf " Débanni un compte (0 = de-banni).\n"; + } elsif ("block" =~ /^\Q$command/ && length($command) >= 2) { + printf "block <nom compte>\n"; + printf " Place le status d'un compte à 5 (You have been blocked by the GM Team).\n"; + printf " La commande est l'équivalent de state <nom_compte> 5.\n"; + } elsif ("check" =~ /^\Q$command/ && $command ne "c") { # check 1 letter command: 'check' or 'create'? + printf "check <nomcompte> <motdepasse>\n"; + printf " Vérifie la validité d'un mot de passe pour un compte\n"; + printf " NOTE: Le serveur n'enverra jamais un mot de passe.\n"; + printf " C'est la seule méthode que vous possédez pour savoir\n"; + printf " si un mot de passe est le bon. L'autre méthode est\n"; + printf " d'avoir un accès ('physique') au fichier des comptes.\n"; + } elsif ("create" =~ /^\Q$command/ && $command ne "c") { # check 1 letter command: 'check' or 'create'? + printf "create <nomcompte> <sexe> <email> <motdepasse>\n"; + printf " Comme la commande add, mais avec l'e-mail en plus.\n"; + printf " <exemple> create testname Male mon\@mail.com testpass\n"; + } elsif ("del" =~ /^\Q$command/ || "delete" =~ /^\Q$command/) { + printf "del <nomcompte>\n"; + printf " Supprime un compte.\n"; + printf " La commande demande confirmation. Après confirmation, le compte est détruit.\n"; + } elsif ("email" =~ /^\Q$command/ && $command ne "e") { # check 1 letter command: 'email', 'end' or 'exit'? + printf "email <nomcompte> <email>\n"; + printf " Modifie l'e-mail d'un compte.\n"; + } elsif ("getcount" =~ /^\Q$command/ && $command ne "g") { # check 1 letter command: 'getcount' or 'gm'? + printf "getcount\n"; + printf " Donne le nombre de joueurs en ligne par serveur de char.\n"; + } elsif ("gm" =~ /^\Q$command/ && $command ne "g") { # check 1 letter command: 'getcount' or 'gm'? + printf "gm <nomcompte> [Niveau_GM]\n"; + printf " Modifie le niveau de GM d'un compte.\n"; + printf " Valeur par défaut: 0 (suppression du niveau de GM).\n"; + printf " <exemple> gm nomtest 80\n"; + } elsif ("id" =~ /^\Q$command/ && $command ne "i") { # check 1 letter command: 'id' or 'info'? + printf "id <nomcompte>\n"; + printf " Donne l'id d'un compte.\n"; + } elsif ("info" =~ /^\Q$command/ && $command ne "i") { # check 1 letter command: 'id' or 'info'? + printf "info <idcompte>\n"; + printf " Affiche les informations sur un compte.\n"; + } elsif ($command eq "kami") { # check all letters command: 'kami' or 'kamib'? + printf "kami <message>\n"; + printf " Envoi un message général sur tous les serveurs de map (en jaune).\n"; + } elsif ($command eq "kamib") { # check all letters command: 'kami' or 'kamib'? + printf "kamib <message>\n"; + printf " Envoi un message général sur tous les serveurs de map (en bleu).\n"; + } elsif ("language" =~ /^\Q$command/ && $command ne "l") { # check 1 letter command: 'list' or 'language'? + printf("language <langue>\n"); + printf(" Change la langue d'affichage.\n"); + printf(" Langues possibles: 'Français' ou 'English'.\n"); + } elsif (("list" =~ /^\Q$command/ || $command eq "ls") && $command ne "l") { # check 1 letter command: 'list' or 'language'? + printf "list/ls [Premier_id [Dernier_id]]\n"; + printf " Affiche une liste de comptes.\n"; + printf " 'Premier_id', 'Dernier_id': indique les identifiants de départ et de fin.\n"; + printf " La recherche par nom n'est pas possible avec cette commande.\n"; + printf " <example> list 10 9999999\n"; + } elsif (("listban" =~ /^\Q$command/ || $command eq "lsban") && $command ne "l") { # need to specificaly write Ban to have this list # check 1 letter command: 'list' or 'language'? + printf "listBan/lsBan [Premier_id [Dernier_id]]\n"; + printf " Comme list/ls, mais seulement pour les comptes GM avec un statut ou bannis.\n"; + } elsif (("listgm" =~ /^\Q$command/ || $command eq "lsgm") && $command ne "l") { # need to specificaly write GM to have this list # check 1 letter command: 'list' or 'language'? + printf "listGM/lsGM [Premier_id [Dernier_id]]\n"; + printf " Comme list/ls, mais seulement pour les comptes GM.\n"; + } elsif (("listok" =~ /^\Q$command/ || $command eq "lsok") && $command ne "l") { # need to specificaly write OK to have this list # check 1 letter command: 'list' or 'language'? + printf "listOK/lsOK [Premier_id [Dernier_id]]\n"; + printf " Comme list/ls, mais seulement pour les comptes sans statut et non bannis.\n"; + } elsif ("memo" =~ /^\Q$command/) { + printf "memo <nomcompte> <memo>\n"; + printf " Modifie le mémo d'un compte.\n"; + printf " 'memo': Il peut avoir jusqu'à 253 caractères (avec des espaces ou non).\n"; + } elsif ("name" =~ /^\Q$command/) { + printf "name <idcompte>\n"; + printf " Donne le nom d'un compte.\n"; + } elsif ("passwd" =~ /^\Q$command/ || "password" =~ /^\Q$command/) { + printf "passwd <nomcompte> <nouveaumotdepasse>\n"; + printf " Change le mot de passe d'un compte.\n"; + printf " Lorsque nouveaumotdepasse est omis,\n"; + printf " la saisie se fait sans que la frappe ne se voit.\n"; + } elsif ("reloadgm" =~ /^\Q$command/) { + printf "reloadGM\n"; + printf " Reload GM configuration file\n"; + } elsif ("search" =~ /^\Q$command/ && $command ne "s" && # check 1 letter command: 'search', 'state' or 'sex'? + $command ne "se") { # check 2 letters command: 'search' or 'sex'? + printf "search <expression>\n"; + printf " Cherche des comptes.\n"; + printf " Affiche les comptes dont les noms correspondent.\n"; + printf "search -r/-e/--expr/--regex <expression>\n"; + printf " Cherche des comptes par expression regulière.\n"; + printf " Affiche les comptes dont les noms correspondent.\n"; + } elsif ("sex" =~ /^\Q$command/ && $command ne "s" && # check 1 letter command: 'search', 'state' or 'sex'? + $command ne "se") { # check 2 letters command: 'search' or 'sex'? + printf "sex <nomcompte> <sexe>\n"; + printf " Modifie le sexe d'un compte.\n"; + printf " <exemple> sex testname Male\n"; + } elsif ("state" =~ /^\Q$command/ && $command ne "s") { # check 1 letter command: 'search', 'state' or 'sex'? + printf "state <nomcompte> <nouveaustatut> <message_erreur_7>\n"; + printf " Change le statut d'un compte.\n"; + printf " 'nouveaustatut': Le statut est le même que celui du packet 0x006a + 1.\n"; + printf " les possibilités sont:\n"; + printf " 0 = Compte ok\n"; + printf " 1 = Unregistered ID\n"; + printf " 2 = Incorrect Password\n"; + printf " 3 = This ID is expired\n"; + printf " 4 = Rejected from Server\n"; + printf " 5 = You have been blocked by the GM Team\n"; + printf " 6 = Your Game's EXE file is not the latest version\n"; + printf " 7 = You are Prohibited to log in until...\n"; + printf " 8 = Server is jammed due to over populated\n"; + printf " 9 = No MSG\n"; + printf " 100 = This ID has been totally erased\n"; + printf " all other values are 'No MSG', then use state 9 please.\n"; + printf " 'message_erreur_7': message du code erreur 6 =\n"; + printf " = Your are Prohibited to log in until... (packet 0x006a)\n"; + } elsif (("timeadd" =~ /^\Q$command/ || $command eq "ta") && $command ne "t") { # check 1 letter command: 'ta' or 'ts'? + printf "timeadd <nomcompte> <modificateur>\n"; + printf " Ajoute/soustrait du temps à la limite de validité d'un compte.\n"; + printf " Le modificateur est composé comme suit:\n"; + printf " Valeur modificatrice (-1, 1, +1, etc...)\n"; + printf " Elément modifié:\n"; + printf " a ou y: année\n"; + printf " m: mois\n"; + printf " j ou d: jour\n"; + printf " h: heure\n"; + printf " mn: minute\n"; + printf " s: seconde\n"; + printf " <exemple> timeadd testname +1m-2mn1s-6a\n"; + printf " Cette exemple ajoute 1 mois et une seconde, et soustrait 2 minutes\n"; + printf " et 6 ans dans le même temps.\n"; + printf "NOTE: Vous ne pouvez pas modifier une limite de validité illimitée. Si vous\n"; + printf " désirez le faire, c'est que vous voulez probablement créer un limite de\n"; + printf " validité limitée. Donc, en premier, fixé une limite de valitidé.\n"; + } elsif (("timeset" =~ /^\Q$command/ || $command eq "ts") && $command ne "t") { # check 1 letter command: 'ta' or 'ts'? + printf "timeset <nomcompte> aaaa/mm/jj [hh:mm:ss]\n"; + printf " Change la limite de validité d'un compte.\n"; + printf " Heure par défaut: 23:59:59\n"; + printf "timeset <nomcompte> 0\n"; + printf " Donne une limite de validité illimitée (0 = illimitée).\n"; + } elsif ($command eq "unban" || ("unbanish" =~ /^\Q$command/ && length($command) >= 4)) { + printf "unban/unbanish <nom compte>\n"; + printf " Ote le banissement d'un compte.\n"; + printf " La commande est l'équivalent de banset <nom_compte> 0.\n"; + } elsif ("unblock" =~ /^\Q$command/ && length($command) >= 4) { + printf "unblock <nom compte>\n"; + printf " Place le status d'un compte à 0 (Compte ok).\n"; + printf " La commande est l'équivalent de state <nom_compte> 0.\n"; + } elsif ("version" =~ /^\Q$command/) { + printf "version\n"; + printf " Affiche la version du login-serveur.\n"; + } elsif ("who" =~ /^\Q$command/) { + printf "who <nomcompte>\n"; + printf " Affiche les informations sur un compte.\n"; + } elsif ("quit" =~ /^\Q$command/ || + (("end" =~ /^\Q$command/ || "exit" =~ /^\Q$command/) && $command ne "e")) { # check 1 letter command: 'email', 'end' or 'exit'?\n"; + printf "quit/end/exit\n"; + printf " Fin du programme d'administration.\n"; + } else { + if ($receivedcommand ne "") { + printf "Commande inconnue [%s] pour l'aide. Affichage de toutes les commandes.\n", $receivedcommand; + } + print << "ENDOFAIDE"; + aide/help/? -- Affiche cet aide + aide/help/? [commande] -- Affiche l'aide de la commande + add <nomcompte> <sexe> <motdepasse> -- Crée un compte (sans email) + ban/banish aaaa/mm/jj hh:mm:ss <nomcompte>-- Change la date finale de banismnt + banadd/ba <nomcompte> <modificateur> -- Ajout/soustrait du temps à la + exemple: ba moncompte +1m-2mn1s-2y date finale de banissement + banset/bs <nomcompte> aaaa/mm/jj [hh:mm:ss] -- Change la date fin de banisemnt + banset/bs <nomcompte> 0 -- Dé-banis un compte. + block <nom compte> -- Mets le status d'un compte à 5 (blocked by the GM Team) + check <nomcompte> <motdepasse> -- Vérifie un mot de passe d'un compte + create <nomcompte> <sexe> <email> <motdepasse> -- Crée un compte (avec email) + del <nomcompte> -- Supprime un compte + email <nomcompte> <email> -- Modifie l'e-mail d'un compte + getcount -- Donne le nb de joueurs en ligne + gm <nomcompte> [Niveau_GM] -- Modifie le niveau de GM d'un compte + id <nomcompte> -- Donne l'id d'un compte + info <idcompte> -- Affiche les infos sur un compte + kami <message> -- Envoi un message général (en jaune) + kamib <message> -- Envoi un message général (en bleu) + language <langue> -- Change la langue d'affichage. + list/ls [Premier_id [Dernier_id] ] -- Affiche une liste de comptes + listBan/lsBan [Premier_id [Dernier_id] ]-- Affiche une liste de comptes + avec un statut ou bannis + listGM/lsGM [Premier_id [Dernier_id] ] -- Affiche une liste de comptes GM + listOK/lsOK [Premier_id [Dernier_id] ] -- Affiche une liste de comptes + sans status et non bannis + memo <nomcompte> <memo> -- Modifie le memo d'un compte + name <idcompte> -- Donne le nom d'un compte + passwd <nomcompte> <nouveaumotdepasse> -- Change le mot de passe d'un compte + quit/end/exit -- Fin du programme d'administation + reloadGM -- Recharger le fichier de config des GM + search <expression> -- Cherche des comptes + search -e/-r/--expr/--regex <expression> -- Cherche des comptes par REGEX + sex <nomcompte> <sexe> -- Modifie le sexe d'un compte + state <nomcompte> <nouveaustatut> <messageerr7> -- Change le statut d'1 compte + timeadd/ta <nomcompte> <modificateur> -- Ajout/soustrait du temps à la + exemple: ta moncompte +1m-2mn1s-2y limite de validité + timeset/ts <nomcompte> aaaa/mm/jj [hh:mm:ss] -- Change la limite de validité + timeset/ts <nomcompte> 0 -- limite de validité = illimitée + unban/unbanish <nom compte> -- Ote le banissement d'un compte + unblock <nom compte> -- Mets le status d'un compte à 0 (Compte ok) + version -- Donne la version du login-serveur + who <nomcompte> -- Affiche les infos sur un compte +ENDOFAIDE + printf(" Note: Pour les noms de compte avec des espaces, tapez \"<nom compte>\" (ou ').\n"); + } + } else { + if ("aide" =~ /^\Q$command/ && $command ne "a") { # check 1 letter command: 'aide' or 'add'? + printf "aide/help/?\n"; + printf " Display the description of the commands\n"; + printf "aide/help/? [command]\n"; + printf " Display the description of the specified command\n"; + } elsif ("help" =~ /^\Q$command/) { + printf "aide/help/?\n"; + printf " Display the description of the commands\n"; + printf "aide/help/? [command]\n"; + printf " Display the description of the specified command\n"; + } elsif ("add" =~ /^\Q$command/ && $command ne "a") { # check 1 letter command: 'aide' or 'add'? + printf "add <account_name> <sex> <password>\n"; + printf " Create an account with the default email (a\@a.com).\n"; + printf " Concerning the sex, only the first letter is used (F or M).\n"; + printf " The e-mail is set to a\@a.com (default e-mail). It's like to have no e-mail.\n"; + printf " When the password is omitted,\n"; + printf " the input is done without displaying of the pressed keys.\n"; + printf " <example> add testname Male testpass\n"; + } elsif ($command eq "ban" || ("banish" =~ /^\Q$command/ && length($command) >= 4)) { + printf "ban/banish yyyy/mm/dd hh:mm:ss <account_name>\n"; + printf " Changes the final date of a banishment of an account.\n"; + printf " The difference with banset is the position of the account name.\n"; + } elsif (("banadd" =~ /^\Q$command/ || $command eq "ba") && $command ne "b") { # check 1 letter command: 'ba' or 'bs'? + printf "banadd <account_name> <modifier>\n"; + printf " Adds or substracts time from the final date of a banishment of an account.\n"; + printf " Modifier is done as follows:\n"; + printf " Adjustment value (-1, 1, +1, etc...)\n"; + printf " Modified element:\n"; + printf " a or y: year\n"; + printf " m: month\n"; + printf " j or d: day\n"; + printf " h: hour\n"; + printf " mn: minute\n"; + printf " s: second\n"; + printf " <example> banadd testname +1m-2mn1s-6y\n"; + printf " this example adds 1 month and 1 second, and substracts 2 minutes\n"; + printf " and 6 years at the same time.\n"; + printf "NOTE: If you modify the final date of a non-banished account,\n"; + printf " you fix the final date to (actual time +- adjustments)\n"; + } elsif (("banset" =~ /^\Q$command/ || $command eq "bs") && $command ne "b") { # check 1 letter command: 'ba' or 'bs'? + printf "banset <account_name> yyyy/mm/dd [hh:mm:ss]\n"; + printf " Changes the final date of a banishment of an account.\n"; + printf " Default time: 23:59:59\n"; + printf "banset <account_name> 0\n"; + printf " Set a non-banished account (0 = unbanished).\n"; + } elsif ("block" =~ /^\Q$command/ && length($command) >= 2) { + printf "block <account name>\n"; + printf " Set state 5 (You have been blocked by the GM Team) to an account.\n"; + printf " Same command of state <account_name> 5.\n"; + } elsif ("check" =~ /^\Q$command/ && $command ne "c") { # check 1 letter command: 'check' or 'create'? + printf "check <account_name> <password>\n"; + printf " Check the validity of a password for an account.\n"; + printf " NOTE: Server will never sends back a password.\n"; + printf " It's the only method you have to know if a password is correct.\n"; + printf " The other method is to have a ('physical') access to the accounts file.\n"; + } elsif ("create" =~ /^\Q$command/ && $command ne "c") { # check 1 letter command: 'check' or 'create'? + printf "create <account_name> <sex> <email> <password>\n"; + printf " Like the 'add' command, but with e-mail moreover.\n"; + printf " <example> create testname Male my\@mail.com testpass\n"; + } elsif ("del" =~ /^\Q$command/ || "delete" =~ /^\Q$command/) { + printf "del <account_name>\n"; + printf " Remove an account.\n"; + printf " This order requires confirmation. After confirmation, the account is deleted.\n"; + } elsif ("email" =~ /^\Q$command/ && $command ne "e") { # check 1 letter command: 'email', 'end' or 'exit'? + printf "email <account_name> <email>\n"; + printf " Modify the e-mail of an account.\n"; + } elsif ("getcount" =~ /^\Q$command/ && $command ne "g") { # check 1 letter command: 'getcount' or 'gm'? + printf "getcount\n"; + printf " Give the number of players online on all char-servers.\n"; + } elsif ("gm" =~ /^\Q$command/ && $command ne "g") { # check 1 letter command: 'getcount' or 'gm'? + printf "gm <account_name> [GM_level]\n"; + printf " Modify the GM level of an account.\n"; + printf " Default value remove GM level (GM level = 0).\n"; + printf " <example> gm testname 80\n"; + } elsif ("id" =~ /^\Q$command/ && $command ne "i") { # check 1 letter command: 'id' or 'info'? + printf "id <account_name>\n"; + printf " Give the id of an account.\n"; + } elsif ("info" =~ /^\Q$command/ && $command ne "i") { # check 1 letter command: 'id' or 'info'? + printf "info <account_id>\n"; + printf " Display complete information of an account.\n"; + } elsif ($command eq "kami") { # check all letters command: 'kami' or 'kamib'? + printf "kami <message>\n"; + printf " Sends a broadcast message on all map-server (in yellow).\n"; + } elsif ($command eq "kamib") { # check all letters command: 'kami' or 'kamib'? + printf "kamib <message>\n"; + printf " Sends a broadcast message on all map-server (in blue).\n"; + } elsif ("language" =~ /^\Q$command/ && $command ne "l") { # check 1 letter command: 'list' or 'language'? + printf("language <language>\n"); + printf(" Change the language of displaying.\n"); + printf(" Possible languages: Français or English.\n"); + } elsif (("list" =~ /^\Q$command/ || $command eq "ls") && $command ne "l") { # check 1 letter command: 'list' or 'language'? + printf "list/ls [start_id [end_id]]\n"; + printf " Display a list of accounts.\n"; + printf " 'start_id', 'end_id': indicate end and start identifiers.\n"; + printf " Research by name is not possible with this command.\n"; + printf " <example> list 10 9999999\n"; + } elsif (("listban" =~ /^\Q$command/ || $command eq "lsban") && $command ne "l") { # need to specificaly write Ban to have this list # check 1 letter command: 'list' or 'language'? + printf "listBan/lsBan [start_id [end_id]]\n"; + printf " Like list/ls, but only for accounts with state or banished.\n"; + } elsif (("listgm" =~ /^\Q$command/ || $command eq "lsgm") && $command ne "l") { # need to specificaly write GM to have this list # check 1 letter command: 'list' or 'language'? + printf "listGM/lsGM [start_id [end_id]]\n"; + printf " Like list/ls, but only for GM accounts.\n"; + } elsif (("listok" =~ /^\Q$command/ || $command eq "lsok") && $command ne "l") { # need to specificaly write OK to have this list # check 1 letter command: 'list' or 'language'? + printf "listOK/lsOK [start_id [end_id]]\n"; + printf " Like list/ls, but only for accounts without state and not banished.\n"; + } elsif ("memo" =~ /^\Q$command/) { + printf "memo <account_name> <memo>\n"; + printf " Modify the memo of an account.\n"; + printf " 'memo': it can have until 253 characters (with spaces or not).\n"; + } elsif ("name" =~ /^\Q$command/) { + printf "name <account_id>\n"; + printf " Give the name of an account.\n"; + } elsif ("passwd" =~ /^\Q$command/ || "password" =~ /^\Q$command/) { + printf "passwd <account_name> <new_password>\n"; + printf " Change the password of an account.\n"; + printf " When new password is omitted,\n"; + printf " the input is done without displaying of the pressed keys.\n"; + } elsif ("reloadgm" =~ /^\Q$command/) { + printf "reloadGM\n"; + printf " Reload GM configuration file\n"; + } elsif ("search" =~ /^\Q$command/ && $command ne "s" && # check 1 letter command: 'search', 'state' or 'sex'? + $command ne "se") { # check 2 letters command: 'search' or 'sex'? + printf "search <expression>\n"; + printf " Seek accounts.\n"; + printf " Displays the accounts whose names correspond.\n"; + printf "search -r/-e/--expr/--regex <expression>\n"; + printf " Seek accounts by regular expression.\n"; + printf " Displays the accounts whose names correspond.\n"; + } elsif ("sex" =~ /^\Q$command/ && $command ne "s" && # check 1 letter command: 'search', 'state' or 'sex'? + $command ne "se") { # check 2 letters command: 'search' or 'sex'? + printf "sex <account_name> <sex>\n"; + printf " Modify the sex of an account.\n"; + printf " <example> sex testname Male\n"; + } elsif ("state" =~ /^\Q$command/ && $command ne "s") { # check 1 letter command: 'search', 'state' or 'sex'? + printf "state <account_name> <new_state> <error_message_#7>\n"; + printf " Change the state of an account.\n"; + printf " 'new_state': state is the state of the packet 0x006a + 1.\n"; + printf " The possibilities are:\n"; + printf " 0 = Account ok\n"; + printf " 1 = Unregistered ID\n"; + printf " 2 = Incorrect Password\n"; + printf " 3 = This ID is expired\n"; + printf " 4 = Rejected from Server\n"; + printf " 5 = You have been blocked by the GM Team\n"; + printf " 6 = Your Game's EXE file is not the latest version\n"; + printf " 7 = You are Prohibited to log in until...\n"; + printf " 8 = Server is jammed due to over populated\n"; + printf " 9 = No MSG\n"; + printf " 100 = This ID has been totally erased\n"; + printf " all other values are 'No MSG', then use state 9 please.\n"; + printf " 'error_message_#7': message of the code error 6\n"; + printf " = Your are Prohibited to log in until... (packet 0x006a)\n"; + } elsif (("timeadd" =~ /^\Q$command/ || $command eq "ta") && $command ne "t") { # check 1 letter command: 'ta' or 'ts'? + printf "timeadd <account_name> <modifier>\n"; + printf " Adds or substracts time from the validity limit of an account.\n"; + printf " Modifier is done as follows:\n"; + printf " Adjustment value (-1, 1, +1, etc...)\n"; + printf " Modified element:\n"; + printf " a or y: year\n"; + printf " m: month\n"; + printf " j or d: day\n"; + printf " h: hour\n"; + printf " mn: minute\n"; + printf " s: second\n"; + printf " <example> timeadd testname +1m-2mn1s-6y\n"; + printf " this example adds 1 month and 1 second, and substracts 2 minutes\n"; + printf " and 6 years at the same time.\n"; + printf "NOTE: You can not modify a unlimited validity limit.\n"; + printf " If you want modify it, you want probably create a limited validity limit.\n"; + printf " So, at first, you must set the validity limit to a date/time.\n"; + } elsif (("timeset" =~ /^\Q$command/ || $command eq "ts") && $command ne "t") { # check 1 letter command: 'ta' or 'ts'? + printf "timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n"; + printf " Changes the validity limit of an account.\n"; + printf " Default time: 23:59:59\n"; + printf "timeset <account_name> 0\n"; + printf " Gives an unlimited validity limit (0 = unlimited).\n"; + } elsif ($command eq "unban" || ("unbanish" =~ /^\Q$command/ && length($command) >= 4)) { + printf "unban/unbanish <account name>\n"; + printf " Remove the banishment of an account.\n"; + printf " This command works like banset <account_name> 0.\n"; + } elsif ("unblock" =~ /^\Q$command/ && length($command) >= 4) { + printf "unblock <account name>\n"; + printf " Set state 0 (Account ok) to an account.\n"; + printf " This command works like state <account_name> 0.\n"; + } elsif ("version" =~ /^\Q$command/) { + printf "version\n"; + printf " Display the version of the login-server.\n"; + } elsif ("who" =~ /^\Q$command/) { + printf "who <account_name>\n"; + printf " Displays complete information of an account.\n"; + } elsif ("quit" =~ /^\Q$command/ || + (("end" =~ /^\Q$command/ || "exit" =~ /^\Q$command/) && $command ne "e")) { # check 1 letter command: 'email', 'end' or 'exit'?\n"; + printf "quit/end/exit\n"; + printf " End of the program of administration.\n"; + } else { + if ($receivedcommand ne "") { + printf "Unknown command [%s] for help. Displaying of all commands.\n", $receivedcommand; + } + print << "ENDOFHELP"; + aide/help/? -- Display this help + aide/help/? [command] -- Display the help of the command + add <account_name> <sex> <password> -- Create an account with default email + ban/banish yyyy/mm/dd hh:mm:ss <account_name> -- Change final date of a ban + banadd/ba <account_name> <modifier> -- Add or substract time from the final + example: ba apple +1m-2mn1s-2y date of a banishment of an account + banset/bs <account_name> yyyy/mm/dd [hh:mm:ss] -- Change final date of a ban + banset/bs <account_name> 0 -- Un-banish an account + block <account name> -- Set state 5 (blocked by the GM Team) to an account + check <account_name> <password> -- Check the validity of a password + create <account_name> <sex> <email> <passwrd> -- Create an account with email + del <account_name> -- Remove an account + email <account_name> <email> -- Modify an email of an account + getcount -- Give the number of players online + gm <account_name> [GM_level] -- Modify the GM level of an account + id <account_name> -- Give the id of an account + info <account_id> -- Display all information of an account + kami <message> -- Sends a broadcast message (in yellow) + kamib <message> -- Sends a broadcast message (in blue) + language <language> -- Change the language of displaying. + list/ls [First_id [Last_id]] -- Display a list of accounts + listBan/lsBan [First_id [Last_id]] -- Display a list of accounts + with state or banished + listGM/lsGM [First_id [Last_id]] -- Display a list of GM accounts + listOK/lsOK [First_id [Last_id]] -- Display a list of accounts + without state and not banished + memo <account_name> <memo> -- Modify the memo of an account + name <account_id> -- Give the name of an account + passwd <account_name> <new_password> -- Change the password of an account + quit/end/exit -- End of the program of administation + reloadGM -- Reload GM configuration file + search <expression> -- Seek accounts + search -e/-r/--expr/--regex <expressn> -- Seek accounts by regular-expression + sex <nomcompte> <sexe> -- Modify the sex of an account + state <account_name> <new_state> <error_message_#7> -- Change the state + timeadd/ta <account_name> <modifier> -- Add or substract time from the + example: ta apple +1m-2mn1s-2y validity limit of an account + timeset/ts <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the validify limit + timeset/ts <account_name> 0 -- Give a unlimited validity limit + unban/unbanish <account name> -- Remove the banishment of an account + unblock <account name> -- Set state 0 (Account ok) to an account + version -- Gives the version of the login-server + who <account_name> -- Display all information of an account +ENDOFHELP + printf(" Note: To use spaces in an account name, type \"<account name>\" (or ').\n"); + } + } + + return 0; +} +#-------------------------------------------------------------------------- + +# Sub-function: Displaying of the accounts list +sub listaccount() { + my($st, $ed, $listflag) = @_; + my($i); + my($n) = (0); + # 0123456789 01 01234567890123456789012301234 012345 0123456789012345678901234567 + if ($defaultlanguage eq "F") { + print " id_compte GM nom_utilisateur sexe count statut\n"; + } else { + print "account_id GM user_name sex count state\n"; + } + print "-------------------------------------------------------------------------------\n"; + while(1) { + print $so pack("vV2", 0x7920, $st, $ed); + $so->flush(); + $buf = readso(4); + if (unpack("v", $buf) != 0x7921) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + exit(10); + } + my($len) = unpack("x2v", $buf); + last if ($len <= 4); + for($i = 4; $i < $len; $i += 38) { + my(@dat) = unpack("VCa24cVV", readso(38)); + $st = $dat[0] + 1; + if ($listflag == 0 || + ($listflag == 1 && $dat[1] > 0) || # check GM flag + ($listflag == 3 && $dat[5] != 0) || # check with state or banished + ($listflag == 4 && $dat[5] == 0)) { # check without state and not banished + printf "%10d %2s %-24s%-5s %6d %-27s\n", $dat[0], + ($dat[1] == 0 ? " " : $dat[1]), + $dat[2], + ($defaultlanguage eq "F" ? ("Femme","Male","Servr")[$dat[3]] : ("Femal","Male","Servr")[$dat[3]]), + $dat[4], + (($defaultlanguage eq "F" ? "Compte Ok" : "Account OK"), + "Unregistered ID", + "Incorrect Password", + "This ID is expired", + "Rejected from Server", + "Blocked by the GM Team", # You have been blocked by the GM Team + "Your EXE file is too old", # Your Game's EXE file is not the latest version + "Banishement or\n Prohibited to login until %s", # You are Prohibited to log in until %s + "Server is over populated", # Server is jammed due to over populated + "No MSG", + "This ID is totally erased")[$dat[5] == 100 ? 10 : $dat[5]]; # This ID has been totally erased + $n++; + } + } + } + if ($defaultlanguage eq "F") { + if ($n == 0) { + print "Aucun compte trouvé.\n"; + } elsif ($n == 1) { + print "1 compte trouvé.\n"; + } else { + print "$n comptes trouvés.\n"; + } + } else { + if ($n == 0) { + print "No account found.\n"; + } elsif ($n == 1) { + print "1 account found.\n"; + } else { + print "$n accounts found.\n"; + } + } + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: add an account with the default e-mail +sub addaccount() { + my($userid, $sex, $passwd) = @_; + if ($userid eq "" || !defined($userid)) { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple> add nomtest Male motdepassetest\n"; + } else { + print "Please input an account name.\n"; + print "<example> add testname Male testpass\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } +# if ($userid =~ /[^A-Za-z0-9\@-_]/) { +# if ($defaultlanguage eq "F") { +# print "Caractère interdit trouvé dans le nom du compte ".$`."[${&}]${'}\n"; +# } else { +# print "Illegal character found in the account name ".$`."[${&}]${'}\n"; +# } +# return 101; +# } + $sex = uc(substr($sex, 0, 1)); + if ($sex !~ /^[MF]$/) { + if ($defaultlanguage eq "F") { + print "Sexe incorrect [$sex]. Entrez M ou F svp.\n"; + } else { + print "Illegal gender [$sex]. Please input M or F.\n"; + } + return 103; + } + if ($passwd eq "") { + return 108 if (($passwd = typepasswd()) eq ""); + } + if (verify_password($passwd) == 0) { + return 104; + } + print $so pack("va24a24a1a40", 0x7930, $userid, $passwd, $sex, ""); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x7931) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 106; + } + $buf = readso(28); + if (unpack("V", $buf) == -1 || unpack("V", $buf) == 4294967295) { + if ($defaultlanguage eq "F") { + print "Echec à la création du compte [$userid]. Un compte identique existe déjà.\n"; + } else { + print "Account [$userid] creation failed. Same account already exists.\n"; + } + return 107; + } else { + if ($defaultlanguage eq "F") { + printf "Compte [$userid] créé avec succès [id: %d].\n", unpack("V",$buf); + } else { + printf "Account [$userid] is successfully created [id: %d].\n", unpack("V",$buf); + } + } + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: add an account with an e-mail +sub createaccount() { + my($userid, $sex, $email, $passwd) = @_; + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple> create nomtest Male mon\@email.com motdepassetest\n"; + } else { + print "Please input an account name.\n"; + print "<example> create testname Male my\@mail.com testpass\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } +# if ($userid =~ /[^A-Za-z0-9\@-_]/) { +# if ($defaultlanguage eq "F") { +# print "Caractère interdit trouvé dans le nom du compte ".$`."[${&}]${'}\n"; +# } else { +# print "Illegal character found in the account name ".$`."[${&}]${'}\n"; +# } +# return 101; +# } + $sex = uc(substr($sex, 0, 1)); + if ($sex !~ /^[MF]$/) { + if ($defaultlanguage eq "F") { + print "Sexe incorrect [$sex]. Entrez M ou F svp.\n"; + } else { + print "Illegal gender [$sex]. Please input M or F.\n"; + } + return 103; + } + if (length($email) < 3) { + if ($defaultlanguage eq "F") { + print "Email trop courte [$email]. Entrez une e-mail valide svp.\n"; + } else { + print "Email is too short [$email]. Please input a valid e-mail.\n"; + } + return 109; + } + if (length($email) > 39) { + if ($defaultlanguage eq "F") { + print "Email trop longue [$email]. Entrez une e-mail de 39 caractères maximum svp.\n"; + } else { + print "Email is too long [$email]. Please input an e-mail with 39 bytes at the most.\n"; + } + return 109; + } + if (verify_email($email) == 0) { + if ($defaultlanguage eq "F") { + print "Email incorrecte [$email]. Entrez une e-mail valide svp.\n"; + } else { + print "Invalid email [$email]. Please input a valid e-mail.\n"; + } + return 109; + } + if ($passwd eq "") { + return 108 if (($passwd = typepasswd()) eq ""); + } + if (verify_password($passwd) == 0) { + return 104; + } + print $so pack("va24a24a1a40", 0x7930, $userid, $passwd, $sex, $email); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x7931) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 106; + } + $buf = readso(28); + if (unpack("V", $buf) == -1 || unpack("V", $buf) == 4294967295) { + if ($defaultlanguage eq "F") { + print "Echec à la création du compte [$userid]. Un compte identique existe déjà.\n"; + } else { + print "Account [$userid] creation failed. Same account already exists.\n"; + } + return 107; + } else { + if ($defaultlanguage eq "F") { + printf "Compte [$userid] créé avec succès [id: %d].\n", unpack("V",$buf); + } else { + printf "Account [$userid] is successfully created [id: %d].\n", unpack("V",$buf); + } + } + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: deletion of an account +sub delaccount() { + my($userid) = @_; + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple> del nomtestasupprimer\n"; + } else { + print "Please input an account name.\n"; + print "<example> del testnametodelete\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } + if ($defaultlanguage eq "F") { + print "** Etes-vous vraiment sûr de vouloir SUPPRIMER le compte [$userid]? (o/n) "; + } else { + print "** Are you really sure to DELETE account [$userid]? (y/n) "; + } + if (lc(substr(<STDIN>, 0, 1)) !~ /[oy]/) { + if ($defaultlanguage eq "F") { + print "Suppression annulée\n."; + } else { + print "Deletion canceled\n"; + } + return 121; + } + print $so pack("va24", 0x7932, $userid); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x7933) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 122; + } + $buf = readso(28); + my($id2, $name) = unpack("Va24", $buf); + while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) { + chop($name); + }; + if ($id2 == -1 || $id2 == 4294967295) { + if ($defaultlanguage eq "F") { + print "Echec de la suppression du compte [$userid]. Le compte n'existe pas.\n"; + } else { + print "Account [$userid] deletion failed. Account doesn't exist.\n"; + } + return 123; + } else { + if ($defaultlanguage eq "F") { + print "Compte [$name][id: $id2] SUPPRIME avec succès.\n"; + } else { + print "Account [$name][id: $id2] is successfully DELETED.\n"; + } + } + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: modification of a password +sub changepasswd() { + my($userid, $passwd) = @_; + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple> passwd nomtest nouveaumotdepasse\n"; + } else { + print "Please input an account name.\n"; + print "<example> passwd testname newpassword\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } + if ($passwd eq "") { + return 134 if (($passwd = typepasswd()) eq ""); + } + if (verify_password($passwd) == 0) { + return 131; + } + print $so pack("va24a24", 0x7934, $userid,$passwd); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x7935) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 132; + } + $buf = readso(28); + my($id2, $name) = unpack("Va24", $buf); + while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) { + chop($name); + }; + if ($id2 == -1 || $id2 == 4294967295) { + if ($defaultlanguage eq "F") { + print "Echec de la modification du mot de passe du compte [$userid].\n"; + print "Le compte [$userid] n'existe pas.\n"; + } else { + print "Account [$userid] password changing failed.\n"; + print "Account [$userid] doesn't exist.\n"; + } + return 133; + } else { + if ($defaultlanguage eq "F") { + print "Modification du mot de passe du compte [$name][id: $id2] réussie.\n"; + } else { + print "Account [$name][id: $id2] password successfully changed.\n"; + } + } + return 130; +} + +#-------------------------------------------------------------------------- + +# Sub-function: modification of an account e-mail +sub changeemail() { + my($userid, $email) = @_; + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple> email testname nouveauemail\n"; + } else { + print "Please input an account name.\n"; + print "<example> email testname newemail\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } + if (length($email) < 3) { + if ($defaultlanguage eq "F") { + print "Email trop courte [$email]. Entrez une e-mail valide svp.\n"; + } else { + print "Email is too short [$email]. Please input a valid e-mail.\n"; + } + return 109; + } + if (length($email) > 39) { + if ($defaultlanguage eq "F") { + print "Email trop longue [$email]. Entrez une e-mail de 39 caractères maximum svp.\n"; + } else { + print "Email is too long [$email]. Please input an e-mail with 39 bytes at the most.\n"; + } + return 109; + } + if (verify_email($email) == 0) { + if ($defaultlanguage eq "F") { + print "Email incorrect [$email]. Entrez une e-mail valide svp.\n"; + } else { + print "Invalid email [$email]. Please input a valid e-mail.\n"; + } + return 109; + } + print $so pack("va24a40", 0x7940, $userid, $email); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x7941) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 162; + } + $buf = readso(28); + my($id2, $name) = unpack("Va24", $buf); + while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) { + chop($name); + }; + if ($id2 == -1 || $id2 == 4294967295) { + if ($defaultlanguage eq "F") { + print "Echec de la modification de l'e-mail du compte [$userid].\n"; + print "Le compte [$userid] n'existe pas.\n"; + } else { + print "Account [$userid] e-mail changing failed.\n"; + print "Account [$userid] doesn't exist.\n"; + } + return 133; + } else { + if ($defaultlanguage eq "F") { + print "Modification de l'e-mail du compte [$name][id: $id2] réussie.\n"; + } else { + print "Account [$name][id: $id2] e-mail successfully changed.\n"; + } + } + return 160; +} + +#-------------------------------------------------------------------------- + +# Sub-function: search of accounts +sub searchaccount() { + my($p1, $p2) = @_; + my($exp) = (""); + if ($p1 eq "-e" || $p1 eq "-r" || $p1 eq "--regex" || $p1 eq "--expr") { + if ($p2 eq "") { + if ($defaultlanguage eq "F") { + print "Entrez une expression régulière ou utilisez 'ls' pour avoir tous les comptes.\n"; + } else { + print "Input a regular expression or use 'ls' to obtain all accounts.\n"; + } + return 141; + } + $exp = $p2; + } else { + if ($p1 eq "") { + if ($defaultlanguage eq "F") { + print "Entrez une chaîne ou utilisez 'ls' pour avoir tous les comptes.\n"; + } else { + print "Input a string or use 'ls' to obtain all accounts.\n"; + } + return 141; + } + my($c) = 0; + $exp = lc($p1); + $exp =~ s/([\@])/\\$1/g; + $c += $exp =~ s/([\-\[\]])/\\$1/g; + $c += $exp =~ s/([\*\?])/.$1/g; + $c += $exp =~ s/\\\[(.)\\\-(.)\\\]/[$1-$2]/g; + $exp = "^$exp\$" if $c; + } + if (eval{ "" =~ /$exp/; }, $@) { + if ($defaultlanguage eq "F") { + print "Expression régulière non reconnue.\n"; + } else { + print "Regular-Expression compiling failed.\n"; + } + return 141; + } + my($i); + my($n, $st) = (0, 0); + # 0123456789 01 01234567890123456789012301234 012345 0123456789012345678901234567 + if ($defaultlanguage eq "F") { + print " id_compte GM nom_utilisateur sexe count statut\n"; + } else { + print "account_id GM user_name sex count state\n"; + } + print "-------------------------------------------------------------------------------\n"; + while(1) { + print $so pack("vV2", 0x7920, $st, 0); + $so->flush(); + $buf = readso(4); + if (unpack("v", $buf) != 0x7921) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + exit(10); + } + my($len) = unpack("x2v", $buf); + last if ($len <= 4); + for($i = 4; $i < $len; $i += 38) { + my(@dat) = unpack("VCa24cVV", readso(38)); + $st = $dat[0] + 1; + next if (lc($dat[2]) !~ /$exp/); + printf "%10d %2s %-24s%-5s %6d %-27s\n", $dat[0], + ($dat[1] == 0 ? " " : $dat[1]), + $dat[2], + ($defaultlanguage eq "F" ? ("Femme","Male","Servr")[$dat[3]] : ("Femal","Male","Servr")[$dat[3]]), + $dat[4], + (($defaultlanguage eq "F" ? "Compte Ok" : "Account OK"), + "Unregistered ID", + "Incorrect Password", + "This ID is expired", + "Rejected from Server", + "Blocked by the GM Team", # You have been blocked by the GM Team + "Your EXE file is too old", # Your Game's EXE file is not the latest version + "Banishement or\n Prohibited to login until %s", # You are Prohibited to log in until %s + "Server is over populated", # Server is jammed due to over populated + "No MSG", + "This ID is totally erased")[$dat[5] == 100 ? 10 : $dat[5]]; # This ID has been totally erased + $n++; + } + } + if ($defaultlanguage eq "F") { + if ($n == 0) { + print "Aucun compte trouvé.\n"; + } elsif ($n == 1) { + print "1 compte trouvé.\n"; + } else { + print "$n comptes trouvés.\n"; + } + } else { + if ($n == 0) { + print "No account found.\n"; + } elsif ($n == 1) { + print "1 account found.\n"; + } else { + print "$n accounts found.\n"; + } + } + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: modify the sex of an account +sub changesex() { + my($userid, $sex) = @_; + if ($userid eq "" || !defined($userid)) { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple> sex nomtest Male\n"; + } else { + print "Please input an account name.\n"; + print "<example> sex testname Male\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } +# if ($userid =~ /[^A-Za-z0-9\@-_]/) { +# if ($defaultlanguage eq "F") { +# print "Caractère interdit trouvé dans le nom du compte ".$`."[${&}]${'}\n"; +# } else { +# print "Illegal character found in the account name ".$`."[${&}]${'}\n"; +# } +# return 101; +# } + $sex = uc(substr($sex, 0, 1)); + if ($sex !~ /^[MF]$/) { + if ($defaultlanguage eq "F") { + print "Sexe incorrect [$sex]. Entrez M ou F svp.\n"; + } else { + print "Illegal gender [$sex]. Please input M or F.\n"; + } + return 103; + } + print $so pack("va24a1", 0x793c, $userid, $sex); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x793d) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 152; + } + $buf = readso(28); + my($id2, $name) = unpack("Va24", $buf); + while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) { + chop($name); + }; + if ($id2 == -1 || $id2 == 4294967295) { + if ($defaultlanguage eq "F") { + print "Echec du changement du sexe du compte [$userid].\n"; + print "Le compte n'existe pas ou le sexe est déjà celui demandé.\n"; + } else { + print "Account [$userid] sex changing failed.\n"; + print "Account doesn't exist or the sex is already the good sex.\n"; + } + } else { + if ($defaultlanguage eq "F") { + print "Sexe du compte [$name][id: $id2] changé avec succès.\n"; + } else { + print "Account [$name][id: $id2] sex successfully changed.\n"; + } + } + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: modify the GM level of an account +sub changegmlevel() { + my($userid, $gm_level) = @_; + if ($userid eq "" || !defined($userid)) { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple> gm nomtest 80\n"; + } else { + print "Please input an account name.\n"; + print "<example> gm testname 80\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } +# if ($userid =~ /[^A-Za-z0-9\@-_]/) { +# if ($defaultlanguage eq "F") { +# print "Caractère interdit trouvé dans le nom du compte ".$`."[${&}]${'}\n"; +# } else { +# print "Illegal character found in the account name ".$`."[${&}]${'}\n"; +# } +# return 101; +# } + $gm_level = int($gm_level); + if ($gm_level < 0 || $gm_level > 99) { + if ($defaultlanguage eq "F") { + print "Niveau de GM incorrect [$gm_level]. Entrez une valeur de 0 à 99 svp.\n"; + } else { + print "Illegal GM level [$gm_level]. Please input a value from 0 to 99.\n"; + } + return 103; + } + print $so pack("va24C", 0x793e, $userid, $gm_level); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x793f) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 152; + } + $buf = readso(28); + my($id2, $name) = unpack("Va24", $buf); + while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) { + chop($name); + }; + if ($id2 == -1 || $id2 == 4294967295) { + if ($defaultlanguage eq "F") { + print "Echec du changement du niveau de GM du compte [$userid].\n"; + print "Le compte n'existe pas, le niveau de GM est déjà celui demandé,\n"; + print "ou il est impossible de modifier le fichier des comptes GM.\n"; + } else { + print "Account [$userid] GM level changing failed.\n"; + print "Account doesn't exist, the GM level is already the good GM level,\n"; + print "or it's impossible to modify the GM accounts file.\n"; + } + } else { + if ($defaultlanguage eq "F") { + print "Niveau de GM du compte [$name][id: $id2] changé avec succès.\n"; + } else { + print "Account [$name][id: $id2] GM level successfully changed.\n"; + } + } + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Modification of a state +sub changestate { + my($userid, $s, $error_message) = @_; + # Valid values: 0: ok, or value of the 0x006a packet + 1 + if ($s eq "" || (($s < 0 || $s > 9) && $s != 100)) { + if ($defaultlanguage eq "F") { + print "Entrez une des valeurs suivantes svp:\n"; + print " 0 = Compte ok 6 = Your Game's EXE file is not the latest version\n"; + } else { + print "Please input one of these values:\n"; + print " 0 = Account ok 6 = Your Game's EXE file is not the latest version\n"; + } + print " 1 = Unregistered ID 7 = You are Prohibited to log in until %s\n"; + print " 2 = Incorrect Password 8 = Server is jammed due to over populated\n"; + print " 3 = This ID is expired 9 = No MSG\n"; + print " 4 = Rejected from Server 100 = This ID has been totally erased\n"; + print " 5 = You have been blocked by the GM Team\n"; + if ($defaultlanguage eq "F") { + print "<exemples> state nomtest 5\n"; + print " state nomtest 7 fin de votre ban\n"; + print " block <nom du compte>\n"; + print " unblock <nom du compte>\n"; + } else { + print "<examples> state testname 5\n"; + print " state testname 7 end of your ban\n"; + print " block <account name>\n"; + print " unblock <account name>\n"; + } + return 151; + } + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemples> state nomtest 5\n"; + print " state nomtest 7 fin de votre ban\n"; + print " block <nom du compte>\n"; + print " unblock <nom du compte>\n"; + } else { + print "Please input an account name.\n"; + print "<examples> state testname 5\n"; + print " state testname 7 end of your ban\n"; + print " block <account name>\n"; + print " unblock <account name>\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } + if ($s != 7) { + $error_message = "-"; + } else { + if (length($error_message) < 1) { + if ($defaultlanguage eq "F") { + print "Message d'erreur trop court. Entrez un message de 1-19 caractères.\n"; + } else { + print "Error message is too short. Please input a message of 1-19 bytes.\n"; + } + return 102; + } + if (length($error_message) > 19) { + if ($defaultlanguage eq "F") { + print "Message d'erreur trop long. Entrez un message de 1-19 caractères.\n"; + } else { + print "Error message is too long. Please input a message of 1-19 bytes.\n"; + } + return 102; + } + } + print $so pack("va24Va20", 0x7936, $userid, $s, $error_message); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x7937) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 152; + } + $buf = readso(32); + my(@dat) = unpack("Va24V", $buf); + while (length($dat[1]) > 0 && substr($dat[1], length($dat[1])-1, 1) eq chr(0)) { + chop($dat[1]); + }; + if ($dat[0] != -1 && $dat[0] != 4294967295) { + if ($defaultlanguage eq "F") { + print "Statut du compte [$dat[1]][id: $dat[0]] changé avec succès en ["; + } else { + print "Account [$dat[1]][id: $dat[0]] state successfully changed in ["; + } + print ((($defaultlanguage eq "F" ? "Compte Ok" : "Account OK"), + "Unregistered ID", + "Incorrect Password", + "This ID is expired", + "Rejected from Server", + "You have been blocked by the GM Team", + "Your Game's EXE file is not the latest version", + "You are Prohibited to log in until %s", + "Server is jammed due to over populated", + "No MSG", + "This ID has been totally erased")[$dat[2] == 100 ? 10 : $dat[2]]); + print "].\n"; + } else { + if ($defaultlanguage eq "F") { + print "Echec du changement du statut du compte [$userid]. Le compte n'existe pas.\n"; + } else { + print "Account [$userid] state changing failed. Account doesn't exist.\n"; + } + } +} + +#-------------------------------------------------------------------------- + +# Sub-function: Displaying of the number of online players +sub getlogincount { + # Request to the login-server + print $so pack("v", 0x7938); + $so->flush(); + + $buf = readso(4); + # Connection failed + if (unpack("v", $buf) != 0x7939) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + exit(3); + } + + # Get length of the received packet + my($len) = unpack("x2v", $buf) - 4; + + # Read information of the servers + if ($len < 1) { + if ($defaultlanguage eq "F") { + printf " Aucun serveur n'est connecté au login serveur.\n"; + } else { + printf " No server is connected to the login-server.\n"; + } + } else { + my(@slist) = (); + for(; $len > 0; $len -= 32) { + my($name, $count) = unpack("x6 a20 V", readso(32)); + $name = substr($name, 0, index($name, "\0")); + push @slist, [ $name, $count ]; + } + # Displaying of result + my($i); + if ($defaultlanguage eq "F") { + printf " Nombre de joueurs en ligne (serveur: nb):\n"; + } else { + printf " Number of online players (server: number).\n"; + } + foreach $i(@slist) { + printf " %-20s : %5d\n", $i->[0], $i->[1]; + } + } +} + +#-------------------------------------------------------------------------- + +# Sub-function: Modification of a memo field +sub changememo { + my($userid, $memo) = @_; + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple> memo nomtest nouveau memo\n"; + } else { + print "Please input an account name.\n"; + print "<example> memo testname new memo\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } + if (length($memo) > 254) { + if ($defaultlanguage eq "F") { + print "Mémo trop long (".length($memo)." caractères).\n"; + print "Entrez un mémo de 254 caractères maximum svp.\n"; + } else { + print "Memo is too long (".length($memo)." characters).\n"; + print "Please input a memo of 254 bytes at the maximum.\n"; + } + return 102; + } + if (length($memo) == 0) { + print $so pack("va24v", 0x7942, $userid, 0); + } else { + print $so pack("va24va".length($memo), 0x7942, $userid, length($memo), $memo); + } + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x7943) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 152; + } + $buf = readso(28); + my($id2, $name) = unpack("Va24", $buf); + while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) { + chop($name); + }; + if ($id2 == -1 || $id2 == 4294967295) { + if ($defaultlanguage eq "F") { + print "Echec du changement du mémo du compte [$userid]. Le compte n'existe pas.\n"; + } else { + print "Account [$userid] memo changing failed. Account doesn't exist.\n"; + } + } else { + if ($defaultlanguage eq "F") { + print "Mémo du compte [$name][id: $id2] changé avec succès.\n"; + } else { + print "Account [$name][id: $id2] memo successfully changed.\n"; + } + } +} + +#-------------------------------------------------------------------------- + +# Sub-function: Request to obtain an account id +sub idaccount() { + my($userid) = @_; + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple> id nomtest\n"; + } else { + print "Please input an account name.\n"; + print "<example> id testname\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } + print $so pack("va24", 0x7944, $userid); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x7945) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 122; + } + $buf = readso(28); + my($id2, $name) = unpack("Va24", $buf); + while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) { + chop($name); + }; + if ($id2 == -1 || $id2 == 4294967295) { + if ($defaultlanguage eq "F") { + print "Impossible de trouver l'id du compte [$userid]. Le compte n'existe pas.\n"; + } else { + print "Unabled to find the account [$userid] id. Account doesn't exist.\n"; + } + return 123; + } else { + if ($defaultlanguage eq "F") { + print "Le compte [$name] a pour id: $id2.\n"; + } else { + print "The account [$name] have the id: $id2.\n"; + } + } + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Request to obtain an account name +sub nameaccount() { + my($id) = @_; + if ($id < 0) { + if ($defaultlanguage eq "F") { + print "Entrez un id ayant une valeur positive svp.\n"; + } else { + print "Please input a positive value for the id.\n"; + } + return 136; + } + print $so pack("vV", 0x7946, $id); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x7947) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 122; + } + $buf = readso(28); + my($id2, $name) = unpack("Va24", $buf); + while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) { + chop($name); + }; + if (length($name) == 0 || $name eq "") { + if ($defaultlanguage eq "F") { + print "Impossible de trouver le nom du compte [id: $id2]. Le compte n'existe pas.\n"; + } else { + print "Unabled to find the account [id: $id2] name. Account doesn't exist.\n"; + } + return 123; + } else { + if ($defaultlanguage eq "F") { + print "Le compte [id: $id2] a pour nom: $name.\n"; + } else { + print "The account [id: $id2] have the name: $name.\n"; + } + } + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Set a validity limit of an account +sub timesetaccount() { + my($userid, $date, $time) = @_; + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple>: timeset <nom_du_compte> aaaa/mm/jj [hh:mm:ss]\n"; + print " timeset <nom_du_compte> 0 (0 = illimité)\n"; + printf " Heure par défaut [hh:mm:ss]: 23:59:59\n"; + } else { + print "Please input an account name.\n"; + print "<example>: timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n"; + print " timeset <account_name> 0 (0 = unlimited)\n"; + printf " Default time [hh:mm:ss]: 23:59:59\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } + my($year, $month, $day) = split(/[.\-\/]/, $date); + my($hour, $minute, $second) = split(/:/, $time); + if ($time eq "") { + $hour = 23; + $minute = 59; + $second = 59; + } + my($timestamp); + if ($year eq "" || + ($year != 0 && ($month eq "" || $day eq "" || $hour eq "" || $minute eq "" || $second eq ""))) { + if ($defaultlanguage eq "F") { + print "Entrez 0 ou une date et une heure svp (format: 0 ou aaaa/mm/jj hh:mm:ss).\n"; + } else { + print "Please input 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n"; + } + return 102; + } + if ($year == 0) { + $timestamp = 0; + } else { + if ($year < 70) { + $year = $year + 100; + } + if ($year >= 1900) { + $year = $year - 1900; + } + if ($month < 1 || $month > 12) { + if ($defaultlanguage eq "F") { + print "Entrez un mois correct svp (entre 1 et 12).\n"; + } else { + print "Please give a correct value for the month (from 1 to 12).\n"; + } + return 102; + } + $month = $month - 1; + if ($day < 1 || $day > 31) { + if ($defaultlanguage eq "F") { + print "Entrez un jour correct svp (entre 1 et 31).\n"; + } else { + print "Please give a correct value for the day (from 1 to 31).\n"; + } + return 102; + } + if ((($month == 3 || $month == 5 || $month == 8 || $month == 10) && $day > 30) || + ($month == 1 && $day > 29)) { + if ($defaultlanguage eq "F") { + print "Entrez un jour correct en fonction du mois svp.\n"; + } else { + print "Please give a correct value for a day of this month.\n"; + } + return 102; + } + if ($hour < 0 || $hour > 23) { + if ($defaultlanguage eq "F") { + print "Entrez une heure correcte svp (entre 0 et 23).\n"; + } else { + print "Please give a correct value for the hour (from 0 to 23).\n"; + } + return 102; + } + if ($minute < 0 || $minute > 59) { + if ($defaultlanguage eq "F") { + print "Entrez des minutes correctes svp (entre 0 et 59).\n"; + } else { + print "Please give a correct value for the minutes (from 0 to 59).\n"; + } + return 102; + } + if ($second < 0 || $second > 59) { + if ($defaultlanguage eq "F") { + print "Entrez des secondes correctes svp (entre 0 et 59).\n"; + } else { + print "Please give a correct value for the seconds (from 0 to 59).\n"; + } + return 102; + } + $timestamp = POSIX::mktime($second, $minute, $hour, $day, $month, $year, 0, 0, -1); # -1: no winter/summer time modification + if ($timestamp == undef) { + if ($defaultlanguage eq "F") { + print "Date incorrecte.\n"; + print "Ajoutez 0 ou une date et une heure svp (format: 0 ou aaaa/mm/jj hh:mm:ss).\n"; + } else { + print "Invalid date.\n"; + print "Please add 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n"; + } + return 102; + } + } + + print $so pack("va24V", 0x7948, $userid, $timestamp); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x7949) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 152; + } + $buf = readso(32); + my(@dat) = unpack("Va24V", $buf); + while (length($dat[1]) > 0 && substr($dat[1], length($dat[1])-1, 1) eq chr(0)) { + chop($dat[1]); + }; + if ($dat[0] != -1 && $dat[0] != 4294967295) { + if ($defaultlanguage eq "F") { + print "Limite de validité du compte [$dat[1]][id: $dat[0]] changée avec succès ". + ($dat[2] == 0 ? "en [illimité].\n" : "pour être jusqu'au ".(POSIX::ctime($dat[2]))); + } else { + print "Validity Limit of the account [$dat[1]][id: $dat[0]] successfully changed ". + ($dat[2] == 0 ? "to [unlimited].\n" : "to be until ".(POSIX::ctime($dat[2]))); + } + # localtime($dat[2]) is also possible to display instead of POSIX::ctime. + } else { + if ($defaultlanguage eq "F") { + print "Echec du changement de la validité du compte [$userid]. Le compte n'existe pas.\n"; + } else { + print "Account [$userid] validity limit changing failed. Account doesn't exist.\n"; + } + } + + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Add/substract time to the validity limit of an account +sub timeaddaccount() { + my($userid, $modif) = @_; + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print " <exemple> timeadd nomtest +1m-2mn1s-6y\n"; + print " Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n"; + print " et 6 ans dans le même temps.\n"; + } else { + print "Please input an account name.\n"; + print " <example> timeadd testname +1m-2mn1s-6y\n"; + print " this example adds 1 month and 1 second, and substracts 2 minutes\n"; + print " and 6 years at the same time.\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } + my($year, $month, $day) = (0, 0 ,0); + my($hour, $minute, $second) = (0, 0 ,0); + + $modif = lc($modif); + while (length($modif) > 0) { + my($value) = int($modif); + if ($value == 0) { + $modif = substr($modif, 1); + } else { + if (substr($modif, 0, 1) =~ /[\-\+]/) { + $modif = substr($modif, 1); + } + while (length($modif) > 0 && substr($modif, 0, 1) =~ /[0-9]/) { + $modif = substr($modif, 1); + } + if (index($modif, "s") == 0) { + $second = $value; + $modif = substr($modif, 1); + } elsif (index($modif, "mn") == 0) { + $minute = $value; + $modif = substr($modif, 2); + } elsif (index($modif, "h") == 0) { + $hour = $value; + $modif = substr($modif, 1); + } elsif (index($modif, "d") == 0 || index($modif, "j") == 0) { + $day = $value; + $modif = substr($modif, 1); + } elsif (index($modif, "m") == 0) { + $month = $value; + $modif = substr($modif, 1); + } elsif (index($modif, "y") == 0 || index($modif, "a") == 0) { + $year = $value; + $modif = substr($modif, 1); + } else { + $modif = substr($modif, 1); + } + } + } + + if ($defaultlanguage eq "F") { + print " année: $year\n"; + print " mois: $month\n"; + print " jour: $day\n"; + print " heure: $hour\n"; + print " minute: $minute\n"; + print " seconde: $second\n"; + } else { + print " year: $year\n"; + print " month: $month\n"; + print " day: $day\n"; + print " hour: $hour\n"; + print " minute: $minute\n"; + print " second: $second\n"; + } + + if ($year == 0 && $month == 0 && $day == 0 && $hour == 0 && $minute == 0 && $second == 0) { + if ($defaultlanguage eq "F") { + print "Vous devez entrer un ajustement avec cette commande, svp:\n"; + print " Valeur d'ajustement (-1, 1, +1, etc...)\n"; + print " Element modifié:\n"; + print " a ou y: année\n"; + print " m: mois\n"; + print " j ou d: jour\n"; + print " h: heure\n"; + print " mn: minute\n"; + print " s: seconde\n"; + print " <exemple> timeadd nomtest +1m-2mn1s-6y\n"; + print " Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n"; + print " et 6 ans dans le même temps.\n"; + } else { + print "Please give an adjustment with this command:\n"; + print " Adjustment value (-1, 1, +1, etc...)\n"; + print " Modified element:\n"; + print " a or y: year\n"; + print " m: month\n"; + print " j or d: day\n"; + print " h: hour\n"; + print " mn: minute\n"; + print " s: second\n"; + print " <example> timeadd testname +1m-2mn1s-6y\n"; + print " this example adds 1 month and 1 second, and substracts 2 minutes\n"; + print " and 6 years at the same time.\n"; + } + return 137; + } + if ($year > 127 || $year < -127) { + if ($defaultlanguage eq "F") { + print "Entrez un ajustement d'années correct (de -127 à 127), svp.\n"; + } else { + print "Please give a correct adjustment for the years (from -127 to 127).\n"; + } + return 137; + } + if ($month > 255 || $month < -255) { + if ($defaultlanguage eq "F") { + print "Entrez un ajustement de mois correct (de -255 à 255), svp.\n"; + } else { + print "Please give a correct adjustment for the months (from -255 to 255).\n"; + } + return 137; + } + if ($day > 32767 || $day < -32767) { + if ($defaultlanguage eq "F") { + print "Entrez un ajustement de jours correct (de -32767 à 32767), svp.\n"; + } else { + print "Please give a correct adjustment for the days (from -32767 to 32767).\n"; + } + return 137; + } + if ($hour > 32767 || $hour < -32767) { + if ($defaultlanguage eq "F") { + print "Entrez un ajustement d'heures correct (de -32767 à 32767), svp.\n"; + } else { + print "Please give a correct adjustment for the hours (from -32767 to 32767).\n"; + } + return 137; + } + if ($minute > 32767 || $minute < -32767) { + if ($defaultlanguage eq "F") { + print "Entrez un ajustement de minutes correct (de -32767 à 32767), svp.\n"; + } else { + print "Please give a correct adjustment for the minutes (from -32767 to 32767).\n"; + } + return 137; + } + if ($second > 32767 || $second < -32767) { + if ($defaultlanguage eq "F") { + print "Entrez un ajustement de secondes correct (de -32767 à 32767), svp.\n"; + } else { + print "Please give a correct adjustment for the seconds (from -32767 to 32767).\n"; + } + return 137; + } + + print $so pack("va24vvvvvv", 0x7950, $userid, $year, $month, $day, $hour, $minute, $second); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x7951) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 152; + } + $buf = readso(32); + my(@dat) = unpack("Va24V", $buf); + while (length($dat[1]) > 0 && substr($dat[1], length($dat[1])-1, 1) eq chr(0)) { + chop($dat[1]); + }; + if ($dat[0] == -1 || $dat[0] == 4294967295) { + if ($defaultlanguage eq "F") { + print "Echec du changement de la validité du compte [$userid]. Le compte n'existe pas.\n"; + } else { + print "Account [$userid] validity limit changing failed. Account doesn't exist.\n"; + } + } elsif ($dat[2] == 0) { + if ($defaultlanguage eq "F") { + print "Limite de validité du compte [$dat[1]][id: $dat[0]] inchangée.\n"; + print "Le compte a une validité illimitée ou\n"; + print "la modification est impossible avec les ajustements demandés.\n"; + } else { + print "Validity limit of the account [$dat[1]][id: $dat[0]] unchanged.\n"; + print "The account have an unlimited validity limit or\n"; + print "the changing is impossible with the proposed adjustments.\n"; + } + } else { + if ($defaultlanguage eq "F") { + print "Limite de validité du compte [$dat[1]][id: $dat[0]] changée avec succès ". + ($dat[2] == 0 ? "en [illimité].\n" : "pour être jusqu'au ".(POSIX::ctime($dat[2]))); + } else { + print "Validity limit of the account [$dat[1]][id: $dat[0]] successfully changed ". + ($dat[2] == 0 ? "to [unlimited].\n" : "to be until ".(POSIX::ctime($dat[2]))); + } + # localtime($dat[2]) is also possible to display instead of POSIX::ctime. + } + + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Set the final date of a banishment of an account +sub bansetaccount() { + my($userid, $date, $time) = @_; + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple>: banset <nom_du_compte> aaaa/mm/jj [hh:mm:ss]\n"; + print " banset <nom_du_compte> 0 (0 = dé-bani)\n"; + print " ban/banish aaaa/mm/jj hh:mm:ss <nom du compte>\n"; + print " unban/unbanish <nom du compte>\n"; + printf " Heure par défaut [hh:mm:ss]: 23:59:59\n"; + } else { + print "Please input an account name.\n"; + print "<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n"; + print " banset <account_name> 0 (0 = un-banished)\n"; + print " ban/banish yyyy/mm/dd hh:mm:ss <account name>\n"; + print " unban/unbanish <account name>\n"; + printf " Default time [hh:mm:ss]: 23:59:59\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } + my($year, $month, $day) = split(/[.\-\/]/, $date); + my($hour, $minute, $second) = split(/:/, $time); + if ($time eq "") { + $hour = 23; + $minute = 59; + $second = 59; + } + my($timestamp); + if ($year eq "" || + ($year != 0 && ($month eq "" || $day eq "" || $hour eq "" || $minute eq "" || $second eq ""))) { + if ($defaultlanguage eq "F") { + print "Entrez 0 ou une date et une heure svp (format: 0 ou aaaa/mm/jj hh:mm:ss).\n"; + } else { + print "Please input 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n"; + } + return 102; + } + if ($year == 0) { + $timestamp = 0; + } else { + if ($year < 70) { + $year = $year + 100; + } + if ($year >= 1900) { + $year = $year - 1900; + } + if ($month < 1 || $month > 12) { + if ($defaultlanguage eq "F") { + print "Entrez un mois correct svp (entre 1 et 12).\n"; + } else { + print "Please give a correct value for the month (from 1 to 12).\n"; + } + return 102; + } + $month = $month - 1; + if ($day < 1 || $day > 31) { + if ($defaultlanguage eq "F") { + print "Entrez un jour correct svp (entre 1 et 31).\n"; + } else { + print "Please give a correct value for the day (from 1 to 31).\n"; + } + return 102; + } + if ((($month == 3 || $month == 5 || $month == 8 || $month == 10) && $day > 30) || + ($month == 1 && $day > 29)) { + if ($defaultlanguage eq "F") { + print "Entrez un jour correct en fonction du mois svp.\n"; + } else { + print "Please give a correct value for a day of this month.\n"; + } + return 102; + } + if ($hour < 0 || $hour > 23) { + if ($defaultlanguage eq "F") { + print "Entrez une heure correcte svp (entre 0 et 23).\n"; + } else { + print "Please give a correct value for the hour (from 0 to 23).\n"; + } + return 102; + } + if ($minute < 0 || $minute > 59) { + if ($defaultlanguage eq "F") { + print "Entrez des minutes correctes svp (entre 0 et 59).\n"; + } else { + print "Please give a correct value for the minutes (from 0 to 59).\n"; + } + return 102; + } + if ($second < 0 || $second > 59) { + if ($defaultlanguage eq "F") { + print "Entrez des secondes correctes svp (entre 0 et 59).\n"; + } else { + print "Please give a correct value for the seconds (from 0 to 59).\n"; + } + return 102; + } + $timestamp = POSIX::mktime($second, $minute, $hour, $day, $month, $year, 0, 0, -1); # -1: no winter/summer time modification + if ($timestamp == undef) { + if ($defaultlanguage eq "F") { + print "Date incorrecte.\n"; + print "Ajoutez 0 ou une date et une heure svp (format: 0 ou aaaa/mm/jj hh:mm:ss).\n"; + } else { + print "Invalid date.\n"; + print "Please add 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n"; + } + return 102; + } + } + + print $so pack("va24V", 0x794a, $userid, $timestamp); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x794b) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 152; + } + $buf = readso(32); + my(@dat) = unpack("Va24V", $buf); + while (length($dat[1]) > 0 && substr($dat[1], length($dat[1])-1, 1) eq chr(0)) { + chop($dat[1]); + }; + if ($dat[0] != -1 && $dat[0] != 4294967295) { + if ($defaultlanguage eq "F") { + print "Date finale de banissement du compte [$dat[1]][id: $dat[0]] changée avec succès ". + ($dat[2] == 0 ? "en [dé-bannie].\n" : "pour être jusqu'au ".(POSIX::ctime($dat[2]))); + } else { + print "Final date of banishment of the account [$dat[1]][id: $dat[0]] successfully changed ". + ($dat[2] == 0 ? "to [unbanished].\n" : "to be until ".(POSIX::ctime($dat[2]))); + } + # localtime($dat[2]) is also possible to display instead of POSIX::ctime. + } else { + if ($defaultlanguage eq "F") { + print "Echec du changement de la date finale de banissement du compte [$userid]. Le compte n'existe pas.\n"; + } else { + print "Account [$userid] final date of banishment changing failed. Account doesn't exist.\n"; + } + } + + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Add/substract time to the final date of a banishment of an account +sub banaddaccount() { + my($userid, $modif) = @_; + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print " <exemple> banadd nomtest +1m-2mn1s-6y\n"; + print " Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n"; + print " et 6 ans dans le même temps.\n"; + } else { + print "Please input an account name.\n"; + print " <example> banadd testname +1m-2mn1s-6y\n"; + print " this example adds 1 month and 1 second, and substracts 2 minutes\n"; + print " and 6 years at the same time.\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } + my($year, $month, $day) = (0, 0 ,0); + my($hour, $minute, $second) = (0, 0 ,0); + + $modif = lc($modif); + while (length($modif) > 0) { + my($value) = int($modif); + if ($value == 0) { + $modif = substr($modif, 1); + } else { + if (substr($modif, 0, 1) =~ /[\-\+]/) { + $modif = substr($modif, 1); + } + while (length($modif) > 0 && substr($modif, 0, 1) =~ /[0-9]/) { + $modif = substr($modif, 1); + } + if (index($modif, "s") == 0) { + $second = $value; + $modif = substr($modif, 1); + } elsif (index($modif, "mn") == 0) { + $minute = $value; + $modif = substr($modif, 2); + } elsif (index($modif, "h") == 0) { + $hour = $value; + $modif = substr($modif, 1); + } elsif (index($modif, "d") == 0 || index($modif, "j") == 0) { + $day = $value; + $modif = substr($modif, 1); + } elsif (index($modif, "m") == 0) { + $month = $value; + $modif = substr($modif, 1); + } elsif (index($modif, "y") == 0 || index($modif, "a") == 0) { + $year = $value; + $modif = substr($modif, 1); + } else { + $modif = substr($modif, 1); + } + } + } + + if ($defaultlanguage eq "F") { + print " année: $year\n"; + print " mois: $month\n"; + print " jour: $day\n"; + print " heure: $hour\n"; + print " minute: $minute\n"; + print " seconde: $second\n"; + } else { + print " year: $year\n"; + print " month: $month\n"; + print " day: $day\n"; + print " hour: $hour\n"; + print " minute: $minute\n"; + print " second: $second\n"; + } + + if ($year == 0 && $month == 0 && $day == 0 && $hour == 0 && $minute == 0 && $second == 0) { + if ($defaultlanguage eq "F") { + print "Vous devez entrer un ajustement avec cette commande, svp:\n"; + print " Valeur d'ajustement (-1, 1, +1, etc...)\n"; + print " Element modifié:\n"; + print " a ou y: année\n"; + print " m: mois\n"; + print " j ou d: jour\n"; + print " h: heure\n"; + print " mn: minute\n"; + print " s: seconde\n"; + print " <exemple> banadd nomtest +1m-2mn1s-6y\n"; + print " Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n"; + print " et 6 ans dans le même temps.\n"; + } else { + print "Please give an adjustment with this command:\n"; + print " Adjustment value (-1, 1, +1, etc...)\n"; + print " Modified element:\n"; + print " a or y: year\n"; + print " m: month\n"; + print " j or d: day\n"; + print " h: hour\n"; + print " mn: minute\n"; + print " s: second\n"; + print " <example> banadd testname +1m-2mn1s-6y\n"; + print " this example adds 1 month and 1 second, and substracts 2 minutes\n"; + print " and 6 years at the same time.\n"; + } + return 137; + } + if ($year > 127 || $year < -127) { + if ($defaultlanguage eq "F") { + print "Entrez un ajustement d'années correct (de -127 à 127), svp.\n"; + } else { + print "Please give a correct adjustment for the years (from -127 to 127).\n"; + } + return 137; + } + if ($month > 255 || $month < -255) { + if ($defaultlanguage eq "F") { + print "Entrez un ajustement de mois correct (de -255 à 255), svp.\n"; + } else { + print "Please give a correct adjustment for the months (from -255 to 255).\n"; + } + return 137; + } + if ($day > 32767 || $day < -32767) { + if ($defaultlanguage eq "F") { + print "Entrez un ajustement de jours correct (de -32767 à 32767), svp.\n"; + } else { + print "Please give a correct adjustment for the days (from -32767 to 32767).\n"; + } + return 137; + } + if ($hour > 32767 || $hour < -32767) { + if ($defaultlanguage eq "F") { + print "Entrez un ajustement d'heures correct (de -32767 à 32767), svp.\n"; + } else { + print "Please give a correct adjustment for the hours (from -32767 to 32767).\n"; + } + return 137; + } + if ($minute > 32767 || $minute < -32767) { + if ($defaultlanguage eq "F") { + print "Entrez un ajustement de minutes correct (de -32767 à 32767), svp.\n"; + } else { + print "Please give a correct adjustment for the minutes (from -32767 to 32767).\n"; + } + return 137; + } + if ($second > 32767 || $second < -32767) { + if ($defaultlanguage eq "F") { + print "Entrez un ajustement de secondes correct (de -32767 à 32767), svp.\n"; + } else { + print "Please give a correct adjustment for the seconds (from -32767 to 32767).\n"; + } + return 137; + } + + print $so pack("va24vvvvvv", 0x794c, $userid, $year, $month, $day, $hour, $minute, $second); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x794d) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 152; + } + $buf = readso(32); + my(@dat) = unpack("Va24V", $buf); + while (length($dat[1]) > 0 && substr($dat[1], length($dat[1])-1, 1) eq chr(0)) { + chop($dat[1]); + }; + if ($dat[0] == -1 || $dat[0] == 4294967295) { + if ($defaultlanguage eq "F") { + print "Echec du changement de la date finale de banissement du compte [$userid]. Le compte n'existe pas.\n"; + } else { + print "Account [$userid] final date of banishment changing failed. Account doesn't exist.\n"; + } + } else { + if ($defaultlanguage eq "F") { + print "Date finale de banissement du compte [$dat[1]][id: $dat[0]] changée avec succès ". + ($dat[2] == 0 ? "en [dé-bannie].\n" : "pour être jusqu'au ".(POSIX::ctime($dat[2]))); + } else { + print "Final date of banishment of the account [$dat[1]][id: $dat[0]] successfully changed ". + ($dat[2] == 0 ? "to [unbanished].\n" : "to be until ".(POSIX::ctime($dat[2]))); + } + # localtime($dat[2]) is also possible to display instead of POSIX::ctime. + } + + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Request to displaying information about an account (by its name) +sub whoaccount() { + my($userid) = @_; + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple> who nomtest\n"; + } else { + print "Please input an account name.\n"; + print "<example> who testname\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } + + print $so pack("va24", 0x7952, $userid); + $so->flush(); + + $buf = readso(2); + if (unpack("v", $buf) != 0x7953) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 122; + } + my($id2, $GM_level, $name, $sex, $count, $status, $error_message, $last_login, $last_ip, $email, $validite, $ban_date, $memo_size) = unpack("VCa24cVVa20a24a16a40VVv", readso(148)); + my($memo) = ""; + if ($memo_size > 0) { + $memo = unpack("a".$memo_size, readso($memo_size)); + } + while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) { + chop($name); + }; + while (length($error_message) > 0 && substr($error_message, length($error_message)-1, 1) eq chr(0)) { + chop($error_message); + }; + while (length($last_login) > 0 && substr($last_login, length($last_login)-1, 1) eq chr(0)) { + chop($last_login); + }; + while (length($last_ip) > 0 && substr($last_ip, length($last_ip)-1, 1) eq chr(0)) { + chop($last_ip); + }; + while (length($email) > 0 && substr($email, length($email)-1, 1) eq chr(0)) { + chop($email); + }; + while (length($memo) > 0 && substr($memo, length($memo)-1, 1) eq chr(0)) { + chop($memo); + }; + + if ($id2 == -1 || $id2 == 4294967295) { + if ($defaultlanguage eq "F") { + print "Impossible de trouver le compte [$userid]. Le compte n'existe pas.\n"; + } else { + print "Unabled to find the account [$userid]. Account doesn't exist.\n"; + } + return 123; + } else { + if ($defaultlanguage eq "F") { + print "Le compte [$userid] a les caractéristiques suivantes:\n"; + } else { + print "The account [$userid] is set with:\n"; + } + if ($GM_level == 0) { + print " Id: $id2 (non-GM)\n"; + } else { + if ($defaultlanguage eq "F") { + print " Id: $id2 (GM niveau $GM_level)\n"; + } else { + print " Id: $id2 (GM level $GM_level)\n"; + } + } + if ($defaultlanguage eq "F") { + print " Nom: '$name'\n"; + print " Sexe: ".("Femme", "Male", "Serveur")[$sex]."\n"; + } else { + print " Name: '$name'\n"; + print " Sex: ".("Female", "Male", "Server")[$sex]."\n"; + } + print " E-mail: $email\n"; + if ($status == 7) { + print " Statut: 7 [You are Prohibited to log in until $error_message]\n"; + } else { + print " Statut: $status [".( + ($defaultlanguage eq "F" ? "Compte Ok" : "Account OK"), + "Unregistered ID", + "Incorrect Password", + "This ID is expired", + "Rejected from Server", + "You have been blocked by the GM Team", + "Your Game's EXE file is not the latest version", + "You are Prohibited to log in until %s", + "Server is jammed due to over populated", + "No MSG", + "This ID is totally erased")[$status == 100 ? 10 : $status]."]\n"; + } + if ($defaultlanguage eq "F") { + print " Banissement: ".($ban_date == 0 ? "non banni.\n" : "jusqu'au ".(POSIX::ctime($ban_date))); + print " Compteur: $count connexion".("s", "")[$count > 1 ? 0 : 1]."\n"; + print " Dernière connexion le: $last_login (ip: $last_ip)\n"; + print " Limite de validité: ".($validite == 0 ? "illimité.\n" : "jusqu'au ".(POSIX::ctime($validite))); + } else { + print " Banishment: ".($ban_date == 0 ? "not banished.\n" : "until ".(POSIX::ctime($ban_date))); + print " Count: $count connection".("s", "")[$count > 1 ? 0 : 1]."\n"; + print " Last connection at: $last_login (ip: $last_ip)\n"; + print " Validity limit: ".($validite == 0 ? "unlimited.\n" : "until ".(POSIX::ctime($validite))); + } + print " Memo: '$memo'\n"; + } + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Request to displaying information about an account (by its id) +sub infoaccount() { + my($id) = @_; + if ($id < 0) { + if ($defaultlanguage eq "F") { + print "Entrez un id ayant une valeur positive svp.\n"; + } else { + print "Please input a positive value for the id.\n"; + } + return 136; + } + + print $so pack("vV", 0x7954, $id); + $so->flush(); + + $buf = readso(2); + if (unpack("v", $buf) != 0x7953) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 122; + } + my($id2, $GM_level, $name, $sex, $count, $status, $error_message, $last_login, $last_ip, $email, $validite, $ban_date, $memo_size) = unpack("VCa24cVVa20a24a16a40VVv", readso(148)); + my($memo) = ""; + if ($memo_size > 0) { + $memo = unpack("a".$memo_size, readso($memo_size)); + } + while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) { + chop($name); + }; + while (length($error_message) > 0 && substr($error_message, length($error_message)-1, 1) eq chr(0)) { + chop($error_message); + }; + while (length($last_login) > 0 && substr($last_login, length($last_login)-1, 1) eq chr(0)) { + chop($last_login); + }; + while (length($last_ip) > 0 && substr($last_ip, length($last_ip)-1, 1) eq chr(0)) { + chop($last_ip); + }; + while (length($email) > 0 && substr($email, length($email)-1, 1) eq chr(0)) { + chop($email); + }; + while (length($memo) > 0 && substr($memo, length($memo)-1, 1) eq chr(0)) { + chop($memo); + }; + + if (length($name) == 0 || $name eq "") { + if ($defaultlanguage eq "F") { + print "Impossible de trouver le nom du compte [id: $id2]. Le compte n'existe pas.\n"; + } else { + print "Unabled to find the account [id: $id2] name. Account doesn't exist.\n"; + } + return 123; + } else { + if ($defaultlanguage eq "F") { + print "Le compte [id: $id2] a les caractéristiques suivantes:\n"; + } else { + print "The account [id: $id2] is set with:\n"; + } + if ($GM_level == 0) { + print " Id: $id2 (non-GM)\n"; + } else { + if ($defaultlanguage eq "F") { + print " Id: $id2 (GM niveau $GM_level)\n"; + } else { + print " Id: $id2 (GM level $GM_level)\n"; + } + } + if ($defaultlanguage eq "F") { + print " Nom: '$name'\n"; + print " Sexe: ".("Femme", "Male", "Serveur")[$sex]."\n"; + } else { + print " Name: '$name'\n"; + print " Sex: ".("Female", "Male", "Server")[$sex]."\n"; + } + print " E-mail: $email\n"; + if ($status == 7) { + print " Statut: 7 [You are Prohibited to log in until $error_message]\n"; + } else { + print " Statut: $status [".( + ($defaultlanguage eq "F" ? "Compte Ok" : "Account OK"), + "Unregistered ID", + "Incorrect Password", + "This ID is expired", + "Rejected from Server", + "You have been blocked by the GM Team", + "Your Game's EXE file is not the latest version", + "You are Prohibited to log in until %s", + "Server is jammed due to over populated", + "No MSG", + "This ID is totally erased")[$status == 100 ? 10 : $status]."]\n"; + } + if ($defaultlanguage eq "F") { + print " Banissement: ".($ban_date == 0 ? "non banni.\n" : "jusqu'au ".(POSIX::ctime($ban_date))); + print " Compteur: $count connexion".("s", "")[$count > 1 ? 0 : 1]."\n"; + print " Dernière connexion le: $last_login (ip: $last_ip)\n"; + print " Limite de validité: ".($validite == 0 ? "illimité.\n" : "jusqu'au ".(POSIX::ctime($validite))); + } else { + print " Banishment: ".($ban_date == 0 ? "not banished.\n" : "until ".(POSIX::ctime($ban_date))); + print " Count: $count connection".("s", "")[$count > 1 ? 0 : 1]."\n"; + print " Last connection at: $last_login (ip: $last_ip)\n"; + print " Validity limit: ".($validite == 0 ? "unlimited.\n" : "until ".(POSIX::ctime($validite))); + } + print " Memo: '$memo'\n"; + } + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Check the validity of a password +# (Note: never send back a password with login-server!! security of passwords) +sub checkaccount() { + my($userid, $passwd) = @_; + if ($userid eq "") { + if ($defaultlanguage eq "F") { + print "Entrez un nom de compte svp.\n"; + print "<exemple> check testname motdepasse\n"; + } else { + print "Please input an account name.\n"; + print "<example> check testname password\n"; + } + return 136; + } + if (verify_accountname($userid) == 0) { + return 102; + } + if ($passwd eq "") { + return 134 if (($passwd = typepasswd()) eq ""); + } + if (verify_password($passwd) == 0) { + return 131; + } + print $so pack("va24a24", 0x793a, $userid,$passwd); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x793b) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 132; + } + $buf = readso(28); + my($id2, $name) = unpack("Va24", $buf); + while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) { + chop($name); + }; + if ($id2 == -1 || $id2 == 4294967295) { + if ($defaultlanguage eq "F") { + print "Le compte [$userid] n'existe pas ou le mot de passe est incorrect.\n"; + } else { + print "The account [$userid] doesn't exist or the password is incorrect.\n"; + } + return 133; + } else { + if ($defaultlanguage eq "F") { + print "Le mot de passe donné correspond bien au compte [$name][id: $id2].\n"; + } else { + print "The proposed password is correct for the account [$name][id: $id2].\n"; + } + } + return 130; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Request to login-server to reload GM configuration file +sub reloadGM() { + print $so pack("v", 0x7955); + $so->flush(); + if ($defaultlanguage eq "F") { + print "Demande de recharger le fichier de configuration des GM envoyée.\n"; + print "Vérifiez les comptes GM actuels (après rechargement):\n"; + } else { + print "Request to reload the GM configuration file sended.\n"; + print "Check the actual GM accounts (after reloading):\n"; + } + &listaccount(0, 0, 1); # 1: to list only GM + return 180; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Send a broadcast message +sub sendbroadcast() { + my($type, $message) = @_; + if ($message eq "" || length($message) == 0) { + if ($defaultlanguage eq "F") { + print "Entrez un message svp.\n"; + if ($type == 0) { + print "<exemple> kami un message\n"; + } else { + print "<exemple> kamib un message\n"; + } + } else { + print "Please input a message.\n"; + if ($type == 0) { + print "<example> kami a message\n"; + } else { + print "<example> kamib a message\n"; + } + } + return 136; + } + + print $so pack("vvVa".length($message), 0x794e, $type, length($message), $message); + $so->flush(); + $buf = readso(2); + if (unpack("v", $buf) != 0x794f) { + if ($defaultlanguage eq "F") { + print "Problème de connexion au serveur (réponse incorrecte).\n"; + } else { + print "Connection error to the server (incorrect answer).\n"; + } + return 152; + } + $buf = readso(2); + my($answer) = unpack("v", $buf); + if ($answer == -1 || $answer == 65535) { + if ($defaultlanguage eq "F") { + print "Echec de l'envoi du message. Aucun server de char en ligne.\n"; + } else { + print "Message sending failed. No online char-server.\n"; + } + } else { + if ($defaultlanguage eq "F") { + print "Message transmis au server de logins avec succès.\n"; + } else { + print "Message successfully sended to login-server.\n"; + } + } +} + +#-------------------------------------------------------------------------- + +# Sub-function: Change language of displaying +sub changelanguage() { + my($language) = @_; + if ($language eq "" || length($language) == 0) { + if ($defaultlanguage == 'F') { + printf("Entrez une langue svp.\n"); + printf("<exemple> language english\n"); + printf(" language français\n"); + } else { + printf("Please input a language.\n"); + printf("<example> language english\n"); + printf(" language français\n"); + } + return 136; + } + + $language = uc(substr($language, 0, 1)); + if ($language =~ /^[EF]$/) { + $defaultlanguage = $language; + if ($defaultlanguage == 'F') { + printf("Changement de la langue d'affichage en Français.\n"); + } else { + printf("Displaying language changed to English.\n"); + } + } else { + if ($defaultlanguage == 'F') { + printf("Langue non paramétrée (langues possibles: 'Français' ou 'English').\n"); + } else { + printf("Undefined language (possible languages: Français or English).\n"); + } + } + + return 0; +} + +#-------------------------------------------------------------------------- + +# Sub-function: sending 'end of connection' packet +sub quit() { + print $so pack("v", 0x7532); + $so->flush(); +} + +#-------------------------------------------------------------------------- + +# Sub-function: Get datas from the socket +sub readso() { + my($len) = shift; + my($buf); + if (read($so, $buf, $len) < $len) { + if ($defaultlanguage eq "F") { + print "Erreur de lecture sur la Socket.\n"; + } else { + print "Socket read error.\n"; + } + exit(3); + } + return $buf; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Input of a password +sub typepasswd { + my($passwd1, $passwd2); + cbreak(); + if ($defaultlanguage eq "F") { + print "Entrez le mot de passe > "; $passwd1 = <STDIN>; chomp($passwd1); print "\n"; + print "Ré-entrez le mot de passe > "; $passwd2 = <STDIN>; chomp($passwd2); print "\n"; + } else { + print "Type the password > "; $passwd1 = <STDIN>; chomp($passwd1); print "\n"; + print "Verify the password > "; $passwd2 = <STDIN>; chomp($passwd2); print "\n"; + } + cooked(); + if ($passwd1 ne $passwd2) { + if ($defaultlanguage eq "F") { + print "Erreur de vérification du mot de passe: Saisissez le même mot de passe svp.\n"; + } else { + print "Password verification failed. Please input same password.\n"; + } + return ""; + } + return $passwd1; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Return ordonal text of a number +sub makeordinal { + my($c) = shift; + if ($defaultlanguage eq "F") { + if ($c < 1) { + return $c; + } + return $c.("er", "ème")[$c == 1 ? 0 : 1]; + } else { + if ($c % 10 < 4 && $c % 10 != 0 && ($c < 10 || $c > 20)) { + return $c.("st","nd","rd")[$c % 10 - 1]; + } + return $c."th"; + } +} + +#-------------------------------------------------------------------------- + +# Sub-function: Test of the validity of an account name (return 0 if incorrect, and 1 if ok) +sub verify_accountname { + my($account_name) = @_; # Get the account_name + if ($account_name =~ /[\x00-\x1f]/) { # remove control char + my($c) = length($`) + 1; + if ($defaultlanguage eq "F") { + print "Caractère interdit trouvé dans le nom du compte (".makeordinal($c)." caractère).\n"; + } else { + print "Illegal character found in the account name (".makeordinal($c)." character).\n"; + } + return 0; + } + if (length($account_name) < 4) { + if ($defaultlanguage eq "F") { + print "Nom du compte trop court. Entrez un nom de compte de 4-23 caractères.\n"; + } else { + print "Account name is too short. Please input an account name of 4-23 bytes.\n"; + } + return 0; + } + if (length($account_name) > 23) { + if ($defaultlanguage eq "F") { + print "Nom du compte trop long. Entrez un nom de compte de 4-23 caractères.\n"; + } else { + print "Account name is too long. Please input an account name of 4-23 bytes.\n"; + } + return 0; + } + return 1; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Test of the validity of password (return 0 if incorrect, and 1 if ok) +sub verify_password { + my($password) = @_; # Get the password + if ($password =~ /[\x00-\x1f]/) { + my($c) = length($`) + 1; + if ($defaultlanguage eq "F") { + print "Caractère interdit trouvé dans le mot de passe (".makeordinal($c)." caractère).\n"; + } else { + print "Illegal character found in the password (".makeordinal($c)." character).\n"; + } + return 0; + } + if (length($password) < 4) { + if ($defaultlanguage eq "F") { + print "Mot de passe trop court. Entrez un mot de passe de 4-23 caractères.\n"; + } else { + print "Password is too short. Please input a password of 4-23 bytes.\n"; + } + return 0; + } + if (length($password) > 23) { + if ($defaultlanguage eq "F") { + print "Mot de passe trop long. Entrez un mot de passe de 4-23 caractères.\n"; + } else { + print "Password is too long. Please input a password of 4-23 bytes.\n"; + } + return 0; + } + return 1; +} + +#-------------------------------------------------------------------------- + +# Sub-function: Test of the validity of an e-mail (return 0 if incorrect, and 1 if ok) +sub verify_email { + my($email) = @_; # Get the e-mail + # To ignore a '.' before the @ (wanadoo, a provider, do that) + $email =~ s/\.\@/\@/; + # If the e-mail is void, it's not correct -> return 0 + if ($email eq '') { + return(0); + } + # If the e-mail have no "@", it's not correct -> return 0 + if ($email !~ /\@/) { + return(0); + } + # If the e-mail have a ",", a space, a tab or a ";", it's not correct -> return 0 + if ($email =~ /[\,|\s|\;]/) { + return(0) + }; + # IF + # (the e-mail contains 2 "@", or ".." or "@." or starts or finishes by a ".") + # OR IF + # (the e-mail doesn't contain "@localhost" AND + # - it doesn't contain characters followed by "@" itself followed by letters itself followed by "." and 2 or more letters + # - or an IP address) + # -> so, it's not good ! (finish !) + if ($email =~ /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)|(\.$)/ || + ($email !~ /^.+\@localhost$/ && + $email !~ /^.+\@\[?(\w|[-.])+\.[a-zA-Z]{2,3}|[0-9]{1,3}\]?$/)) { + return(0); # non-valid email + } else { + # If not, the e-email address is correct + return(1); # valid email + } +}
\ No newline at end of file diff --git a/src/tool/mapcheck.sh b/src/tool/mapcheck.sh new file mode 100644 index 000000000..337884c43 --- /dev/null +++ b/src/tool/mapcheck.sh @@ -0,0 +1,34 @@ +#!/bin/sh +echo "============================================" +echo "= map server status checker... =" +echo "============================================" +./map-server.exe & +sleep 40 + +while [ 0 ] +do + pcpu=` top -n 1| grep map-server | awk '{print $9}' | awk 'BEGIN{FS="."} {print $1}' ` + if [ "$pcpu" -gt 80 ];then + echo "============================================" + echo "map server is more than 80% (now $pcpu%)" + echo "============================================" + ppid=` ps -a | grep map-server | awk '{print $1}' ` + kill $ppid + ./map-server.exe & + sleep 40 + else + pmapct=` ps -a| grep map-server | wc -l ` + if [ "$pmapct" -eq 0 ];then + echo "============================================" + echo "map server is not running..." + echo "restart map server..." + echo "============================================" + ./map-server.exe & + sleep 40 + #echo "test" + else + echo "map server is ok (now $pcpu%)..." + sleep 5 + fi + fi +done
\ No newline at end of file diff --git a/src/tool/mapchecker.sh b/src/tool/mapchecker.sh new file mode 100644 index 000000000..7250c342e --- /dev/null +++ b/src/tool/mapchecker.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +athena_dir="/home/athena/658/" + +while [ true ] ; do + +if [ ` ps fauxw | grep map-server | grep -v grep | wc -l ` -eq 0 ];then + #echo `date` " -- map-server crashed - restarting" + echo `date` " -- map-server crashed - restarting" >> /var/log/athena_status.log + killall -9 map-server + cd $athena_dir + nohup ./map-server ./conf/map_athena.conf ./inter_athena.conf & + sleep 240 + #sleep 40 #for fast pc's remove the "#" at the beginning of the line and delete the line above +fi + + +if [ ` ps fauxw | grep map-server | grep -v grep | awk '{print $3}' | awk 'BEGIN{FS="."} {print $1}' ` -gt 10 ];then + #echo `date` " -- mapserver cpuload over 10 - restarting" + echo `date` " -- mapserver cpuload over 10 - restarting" >> /var/log/athena_status.log + killall -9 map-server + cd $athena_dir + nohup ./map-server ./conf/map_athena.conf ./inter_athena.conf & + sleep 240 + #sleep 40 #for fast pc's remove the "#" at the beginning of the line and delete the line above + #echo `date` " -- restarted" + echo `date` " -- restarted" >> /var/log/athena_status.log +fi + +if [ ` ps fauxw | grep char-server | grep -v grep | wc -l ` -eq 0 ];then + #echo `date` " -- char server crashed - restarting" + echo `date` " -- char server crashed - restarting" >> /var/log/athena_status.log + killall -9 char-server + cd $athena_dir + nohup ./char-server ./conf/char_athena.conf ./conf/inter_athena.conf & + #echo `date` " -- restarted" + echo `date` " -- restarted" >> /var/log/athena_status.log + +fi + +if [ ` ps fauxw | grep login-server | grep -v grep | wc -l ` -eq 0 ];then + #echo `date` " -- login server crashed - restarting" + echo `date` " -- login server crashed - restarting" >> /var/log/athena_status.log + killall -9 login-server + cd $athena_dir + nohup ./login-server ./conf/login_athena.conf & + #echo `date` " -- restarted" + echo `date` " -- restarted" >> /var/log/athena_status.log + +fi + + +#echo `date` " -- everything is fine" +echo `date` " -- everything is fine" >> /var/log/athena_status.log +sleep 30 +done diff --git a/src/txt-converter/char/GNUmakefile b/src/txt-converter/char/GNUmakefile deleted file mode 100644 index 56723ca5a..000000000 --- a/src/txt-converter/char/GNUmakefile +++ /dev/null @@ -1,13 +0,0 @@ -all: char-converter -sql: char-converter - -COMMON_OBJ = ../../common/core.o ../../common/socket.o ../../common/timer.o ../../common/db.o ../../common/malloc.o - -char-converter: char-converter.o strlib.o $(COMMON_OBJ) - $(CC) -o ../../../$@ $^ $(LIB_S) - -char-converter.o: char-converter.c char.h strlib.h -strlib.o: strlib.c strlib.h -clean: - rm -f *.o ../../../char-converter - diff --git a/src/txt-converter/char/Makefile b/src/txt-converter/char/Makefile index 56723ca5a..6b85a04db 100644 --- a/src/txt-converter/char/Makefile +++ b/src/txt-converter/char/Makefile @@ -1,13 +1,13 @@ all: char-converter sql: char-converter -COMMON_OBJ = ../../common/core.o ../../common/socket.o ../../common/timer.o ../../common/db.o ../../common/malloc.o +COMMON_OBJ = ../../common/obj/core.o ../../common/obj/socket.o ../../common/obj/timer.o ../../common/obj/grfio.o ../../common/obj/db.o ../../common/obj/lock.o ../../common/obj/nullpo.o ../../common/obj/malloc.o ../../common/obj/showmsg.o ../../common/obj/strlib.o -char-converter: char-converter.o strlib.o $(COMMON_OBJ) +char-converter: char-converter.o $(COMMON_OBJ) $(CC) -o ../../../$@ $^ $(LIB_S) -char-converter.o: char-converter.c char.h strlib.h -strlib.o: strlib.c strlib.h +char-converter.o: char-converter.c char.h ../../common/strlib.h +strlib.o: strlib.c ../../common/strlib.h clean: rm -f *.o ../../../char-converter diff --git a/src/txt-converter/char/char-converter.c b/src/txt-converter/char/char-converter.c index 8928e240f..217bf2b15 100644 --- a/src/txt-converter/char/char-converter.c +++ b/src/txt-converter/char/char-converter.c @@ -16,16 +16,16 @@ #define STORAGE_MEMINC 16 - + #include "char.h" -#include "strlib.h" +#include "../../common/strlib.h" #ifdef MEMWATCH #include "memwatch.h" #endif - + char pet_txt[256]="save/pet.txt"; -char storage_txt[256]="save/storage.txt"; +char storage_txt[256]="save/storage.txt"; MYSQL mysql_handle; MYSQL_RES* sql_res ; @@ -39,7 +39,7 @@ char db_server_id[32] = "ragnarok"; char db_server_pw[32] = "ragnarok"; char db_server_logindb[32] = "ragnarok"; -struct storage *storage=NULL; +struct storage *storage_=NULL; struct mmo_map_server server[MAX_MAP_SERVERS]; int server_fd[MAX_MAP_SERVERS]; @@ -89,18 +89,18 @@ int inter_pet_fromstr(char *str, struct s_pet *p) int s; int tmp_int[16]; char tmp_str[256]; - + memset(p, 0, sizeof(struct s_pet)); - + // printf("sscanf pet main info\n"); s=sscanf(str,"%d, %d,%[^\t]\t%d, %d, %d, %d, %d, %d, %d, %d, %d", &tmp_int[0], &tmp_int[1], tmp_str, &tmp_int[2], &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10]); if(s!=12) return 1; - + p->pet_id = tmp_int[0]; - p->class = tmp_int[1]; + p->class_ = tmp_int[1]; memcpy(p->name, tmp_str, 24); p->account_id = tmp_int[2]; p->char_id = tmp_int[3]; @@ -126,11 +126,11 @@ int inter_pet_fromstr(char *str, struct s_pet *p) //--------------------------------------------------------- int inter_pet_tosql(int pet_id, struct s_pet *p) { //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) - + char tmp_sql[65535]; MYSQL_RES* sql_res ; MYSQL_ROW sql_row ; - + jstrescapecpy (t_name, p->name); if(p->hungry < 0) p->hungry = 0; @@ -148,19 +148,19 @@ int inter_pet_tosql(int pet_id, struct s_pet *p) { sql_row = mysql_fetch_row(sql_res); //row fetching if (!sql_row) //no row -> insert sprintf(tmp_sql,"INSERT INTO `pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) VALUES ('%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - p->pet_id, p->class, t_name, p->account_id, p->char_id, p->level, p->egg_id, + p->pet_id, p->class_, t_name, p->account_id, p->char_id, p->level, p->egg_id, p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate); else //row reside -> updating sprintf(tmp_sql, "UPDATE `pet` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incuvate`='%d' WHERE `pet_id`='%d'", - p->class, t_name, p->account_id, p->char_id, p->level, p->egg_id, + p->class_, t_name, p->account_id, p->char_id, p->level, p->egg_id, p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate, p->pet_id); mysql_free_result(sql_res) ; //resource free if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); } - + printf ("pet dump success! - %d:%s\n", pet_id, p->name); - + return 0; } @@ -168,27 +168,27 @@ int storage_tosql(int account_id,struct storage *p){ // id -> DB dump // storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`} int i,j; - + j=0; - + //printf ("starting storage dump to DB - id: %d\n", account_id); - + //delete old data. sprintf(tmp_sql,"DELETE FROM `storage` WHERE `account_id`='%d'",account_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); } - + //printf ("all storage item was deleted ok\n"); - + for(i=0;i<MAX_STORAGE;i++) { - //printf ("save storage num: %d (%d:%d)\n",i, p->storage[i].nameid , p->storage[i].amount); - - if( (p->storage[i].nameid) && (p->storage[i].amount) ){ + //printf ("save storage num: %d (%d:%d)\n",i, p->storage_[i].nameid , p->storage_[i].amount); + + if( (p->storage_[i].nameid) && (p->storage_[i].amount) ){ sprintf(tmp_sql,"INSERT INTO `storage` (`account_id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`card0`,`card1`,`card2`,`card3`,`broken`) VALUES ('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - p->account_id, p->storage[i].nameid, p->storage[i].amount, p->storage[i].equip, - p->storage[i].identify, p->storage[i].refine, p->storage[i].attribute, - p->storage[i].card[0], p->storage[i].card[1], p->storage[i].card[2], p->storage[i].card[3], p->storage[i].broken ); + p->account_id, p->storage_[i].nameid, p->storage_[i].amount, p->storage_[i].equip, + p->storage_[i].identify, p->storage_[i].refine, p->storage_[i].attribute, + p->storage_[i].card[0], p->storage_[i].card[1], p->storage_[i].card[2], p->storage_[i].card[3], p->storage_[i].broken ); //printf ("%s\n",tmp_sql); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error - %s\n", mysql_error(&mysql_handle) ); @@ -212,51 +212,51 @@ int storage_fromstr(char *str, struct storage *p) if(set!=2) return 0; if(str[next]=='\n' || str[next]=='\r') - return 1; + return 1; next++; for(i=0;str[next] && str[next]!='\t';i++){ if(sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10], &tmp_int[11], &len) == 12) { - p->storage[i].id = tmp_int[0]; - p->storage[i].nameid = tmp_int[1]; - p->storage[i].amount = tmp_int[2]; - p->storage[i].equip = tmp_int[3]; - p->storage[i].identify = tmp_int[4]; - p->storage[i].refine = tmp_int[5]; - p->storage[i].attribute = tmp_int[6]; - p->storage[i].card[0] = tmp_int[7]; - p->storage[i].card[1] = tmp_int[8]; - p->storage[i].card[2] = tmp_int[9]; - p->storage[i].card[3] = tmp_int[10]; - p->storage[i].broken = tmp_int[11]; + p->storage_[i].id = tmp_int[0]; + p->storage_[i].nameid = tmp_int[1]; + p->storage_[i].amount = tmp_int[2]; + p->storage_[i].equip = tmp_int[3]; + p->storage_[i].identify = tmp_int[4]; + p->storage_[i].refine = tmp_int[5]; + p->storage_[i].attribute = tmp_int[6]; + p->storage_[i].card[0] = tmp_int[7]; + p->storage_[i].card[1] = tmp_int[8]; + p->storage_[i].card[2] = tmp_int[9]; + p->storage_[i].card[3] = tmp_int[10]; + p->storage_[i].broken = tmp_int[11]; next += len; if (str[next] == ' ') - next++; + next++; } else if(sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10], &len) == 11) { - p->storage[i].id = tmp_int[0]; - p->storage[i].nameid = tmp_int[1]; - p->storage[i].amount = tmp_int[2]; - p->storage[i].equip = tmp_int[3]; - p->storage[i].identify = tmp_int[4]; - p->storage[i].refine = tmp_int[5]; - p->storage[i].attribute = tmp_int[6]; - p->storage[i].card[0] = tmp_int[7]; - p->storage[i].card[1] = tmp_int[8]; - p->storage[i].card[2] = tmp_int[9]; - p->storage[i].card[3] = tmp_int[10]; - p->storage[i].broken = 0; + p->storage_[i].id = tmp_int[0]; + p->storage_[i].nameid = tmp_int[1]; + p->storage_[i].amount = tmp_int[2]; + p->storage_[i].equip = tmp_int[3]; + p->storage_[i].identify = tmp_int[4]; + p->storage_[i].refine = tmp_int[5]; + p->storage_[i].attribute = tmp_int[6]; + p->storage_[i].card[0] = tmp_int[7]; + p->storage_[i].card[1] = tmp_int[8]; + p->storage_[i].card[2] = tmp_int[9]; + p->storage_[i].card[3] = tmp_int[10]; + p->storage_[i].broken = 0; next += len; if (str[next] == ' ') - next++; + next++; } - + else return 0; } return 1; @@ -337,7 +337,7 @@ int mmo_char_fromstr(char *str, struct mmo_charstatus *p) { p->char_id = tmp_int[0]; p->account_id = tmp_int[1]; p->char_num = tmp_int[2]; - p->class = tmp_int[3]; + p->class_ = tmp_int[3]; p->base_level = tmp_int[4]; p->job_level = tmp_int[5]; p->base_exp = tmp_int[6]; @@ -508,10 +508,10 @@ int mmo_char_fromstr(char *str, struct mmo_charstatus *p) { //========================================================================================================== int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ int i,save_flag; - + save_flag = char_id; printf("request save char data... (%d)\n",char_id); - + //`char`( `char_id`,`account_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`, //9 //`str`,`agi`,`vit`,`int`,`dex`,`luk`, //15 //`max_hp`,`hp`,`max_sp`,`sp`,`status_point`,`skill_point`, //21 @@ -525,7 +525,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ "`option`='%d',`karma`='%d',`manner`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d'," "`hair`='%d',`hair_color`='%d',`clothes_color`='%d',`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `partner_id` = '%d'", - char_id,p->account_id,p->char_num,p->name,p->class, p->base_level, p->job_level, + char_id,p->account_id,p->char_num,p->name,p->class_, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, p->max_hp, p->hp, p->max_sp, p->sp, p->status_point, p->skill_point, p->str, p->agi, p->vit, p->int_, p->dex, p->luk, @@ -535,17 +535,17 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ p->last_point.map, p->last_point.x, p->last_point.y, p->save_point.map, p->save_point.x, p->save_point.y, p->partner_id ); - + if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (update `char`)- %s\n", mysql_error(&mysql_handle) ); } - + //`memo` (`memo_id`,`char_id`,`map`,`x`,`y`) sprintf(tmp_sql,"DELETE FROM `memo` WHERE `char_id`='%d'",char_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (delete `memo`)- %s\n", mysql_error(&mysql_handle) ); } - + //insert here. for(i=0;i<10;i++){ if(p->memo_point[i].map[0]){ @@ -560,7 +560,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (delete `inventory`)- %s\n", mysql_error(&mysql_handle) ); } - + //insert here. for(i=0;i<MAX_INVENTORY;i++){ if(p->inventory[i].nameid){ @@ -579,7 +579,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (delete `cart_inventory`)- %s\n", mysql_error(&mysql_handle) ); } - + //insert here. for(i=0;i<MAX_CART;i++){ if(p->cart[i].nameid){ @@ -593,14 +593,14 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ } } } - - + + //`skill` (`char_id`, `id`, `lv`) sprintf(tmp_sql,"DELETE FROM `skill` WHERE `char_id`='%d'",char_id); if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (delete `skill`)- %s\n", mysql_error(&mysql_handle) ); } - + //insert here. for(i=0;i<MAX_SKILL;i++){ if(p->skill[i].id){ @@ -618,7 +618,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ if(mysql_query(&mysql_handle, tmp_sql) ) { printf("DB server Error (delete `global_reg_value`)- %s\n", mysql_error(&mysql_handle) ); } - + //insert here. for(i=0;i<p->global_reg_num;i++){ if(p->global_reg[i].value !=0){ @@ -629,10 +629,10 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ } } } - + printf("saving char is done... (%d)\n",char_id); save_flag = 0; - + return 0; } //========================================================================================================== @@ -645,7 +645,7 @@ int mmo_char_init(void){ char input; FILE *fp; - + //DB connection initialized mysql_init(&mysql_handle); printf("Connect DB server.... (inter server)\n"); @@ -658,7 +658,7 @@ int mmo_char_init(void){ else { printf ("connect success! (inter server)\n"); } - + printf("Warning : Make sure you backup your databases before continuing!\n"); @@ -667,14 +667,14 @@ int mmo_char_init(void){ if(input == 'y' || input == 'Y'){ printf("\nConverting Character Database...\n"); fp=fopen("save/athena.txt","r"); - char_dat=malloc(sizeof(char_dat[0])*256); + char_dat = (struct mmo_charstatus*)malloc(sizeof(char_dat[0])*256); char_max=256; if(fp==NULL) return 0; while(fgets(line, 65535, fp)){ if(char_num>=char_max){ char_max+=256; - char_dat=realloc(char_dat, sizeof(char_dat[0]) *char_max); + char_dat = (struct mmo_charstatus*)realloc(char_dat, sizeof(char_dat[0]) *char_max); } memset(&char_dat[char_num], 0, sizeof(char_dat[0])); ret=mmo_char_fromstr(line, &char_dat[char_num]); @@ -689,8 +689,8 @@ int mmo_char_init(void){ printf("char data convert end\n"); fclose(fp); } - - while(getchar() != '\n'); + + while(getchar() != '\n'); printf("\nDo you wish to convert your Storage Database to SQL? (y/n) : "); input=getchar(); if(input == 'y' || input == 'Y') { @@ -700,25 +700,25 @@ int mmo_char_init(void){ printf("cant't read : %s\n",storage_txt); return 0; } - + while(fgets(line,65535,fp)){ set=sscanf(line,"%d,%d",&tmp_int[0],&tmp_int[1]); if(set==2) { if(i==0){ - storage=malloc(sizeof(struct storage)); + storage_ = (struct storage*)malloc(sizeof(struct storage)); }else{ - storage=realloc(storage,sizeof(struct storage)*(i+1)); + storage_ = (struct storage*)realloc(storage_,sizeof(struct storage)*(i+1)); } - memset(&storage[i],0,sizeof(struct storage)); - storage[i].account_id=tmp_int[0]; - storage_fromstr(line,&storage[i]); - storage_tosql(tmp_int[0],&storage[i]); //to sql. (dump) + memset(&storage_[i],0,sizeof(struct storage)); + storage_[i].account_id=tmp_int[0]; + storage_fromstr(line,&storage_[i]); + storage_tosql(tmp_int[0],&storage_[i]); //to sql. (dump) i++; } } fclose(fp); } - + while(getchar() != '\n'); printf("\nDo you wish to convert your Pet Database to SQL? (y/n) : "); input=getchar(); @@ -726,8 +726,8 @@ int mmo_char_init(void){ printf("\nConverting Pet Database...\n"); if( (fp=fopen(pet_txt,"r")) ==NULL ) return 1; - - p=malloc(sizeof(struct s_pet)); + + p = (struct s_pet*)malloc(sizeof(struct s_pet)); while(fgets(line, sizeof(line), fp)){ if(p==NULL){ printf("int_pet: out of memory!\n"); @@ -789,10 +789,13 @@ int inter_config_read(const char *cfgName) { else if(strcmpi(w1,"db_server_logindb")==0){ strcpy(db_server_logindb, w2); printf ("set db_server_logindb : %s\n",w2); + //support the import command, just like any other config + }else if(strcmpi(w1,"import")==0){ + inter_config_read(w2); } } fclose(fp); - + printf("Reading interserver configuration: Done\n"); return 0; @@ -825,7 +828,7 @@ int char_config_read(const char *cfgName) { } fclose(fp); printf("Reading configuration: Done\n"); - + return 0; } diff --git a/src/txt-converter/char/char.h b/src/txt-converter/char/char.h index b5864b31c..e1d5c90dc 100644 --- a/src/txt-converter/char/char.h +++ b/src/txt-converter/char/char.h @@ -24,9 +24,9 @@ struct mmo_map_server{ char map[MAX_MAP_PER_SERVER][16]; }; -int mapif_sendall(unsigned char *buf,unsigned int len); -int mapif_sendallwos(int fd,unsigned char *buf,unsigned int len); -int mapif_send(int fd,unsigned char *buf,unsigned int len); +int mapif_sendall(char *buf,unsigned int len); +int mapif_sendallwos(int fd,char *buf,unsigned int len); +int mapif_send(int fd,char *buf,unsigned int len); extern int autosave_interval; diff --git a/src/txt-converter/char/strlib.c b/src/txt-converter/char/strlib.c deleted file mode 100644 index 60803c1d1..000000000 --- a/src/txt-converter/char/strlib.c +++ /dev/null @@ -1,66 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "strlib.h" - -//----------------------------------------------- -// string lib. -unsigned char* jstrescape (unsigned char* pt) { - //copy from here - unsigned char * ptr; - int i =0, j=0; - - //copy string to temporary - ptr = malloc(J_MAX_MALLOC_SIZE); - strcpy (ptr,pt); - - while (ptr[i] != '\0') { - switch (ptr[i]) { - case '\'': - pt[j++] = '\\'; - pt[j++] = ptr[i++]; - break; - default: - pt[j++] = ptr[i++]; - } - } - pt[j++] = '\0'; - free (ptr); - return (unsigned char*) &pt[0]; -} - -unsigned char* jstrescapecpy (unsigned char* pt,unsigned char* spt) { - //copy from here - int i =0, j=0; - - while (spt[i] != '\0') { - switch (spt[i]) { - case '\'': - pt[j++] = '\\'; - pt[j++] = spt[i++]; - break; - default: - pt[j++] = spt[i++]; - } - } - pt[j++] = '\0'; - return (unsigned char*) &pt[0]; -} -int jmemescapecpy (unsigned char* pt,unsigned char* spt, int size) { - //copy from here - int i =0, j=0; - - while (i < size) { - switch (spt[i]) { - case '\'': - pt[j++] = '\\'; - pt[j++] = spt[i++]; - break; - default: - pt[j++] = spt[i++]; - } - } - // copy size is 0 ~ (j-1) - return j; -} diff --git a/src/txt-converter/char/strlib.h b/src/txt-converter/char/strlib.h deleted file mode 100644 index 442cfac29..000000000 --- a/src/txt-converter/char/strlib.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _J_STR_H_ -#define _J_STR_H_ -#define J_MAX_MALLOC_SIZE 65535 -//string functions. -//code by Jioh L. Jung -unsigned char* jstrescape (unsigned char* pt); -unsigned char* jstrescapecpy (unsigned char* pt,unsigned char* spt); -int jmemescapecpy (unsigned char* pt,unsigned char* spt, int size); -#endif diff --git a/src/txt-converter/common/mmo.h b/src/txt-converter/common/mmo.h index 178046a17..28462e99d 100644 --- a/src/txt-converter/common/mmo.h +++ b/src/txt-converter/common/mmo.h @@ -29,11 +29,11 @@ #define MAX_STORAGE 300 #define MAX_GUILD_STORAGE 1000 #define MAX_PARTY 12 -#define MAX_GUILD 56 // increased max guild members to accomodate for +2 increase for extension levels [Valaris] -#define MAX_GUILDPOSITION 56 // increased max guild positions to accomodate for all members [Valaris] +#define MAX_GUILD 16+10*6 // increased max guild members to accomodate for +6 increase for extension levels [Lupus] +#define MAX_GUILDPOSITION 20 // increased max guild positions to accomodate for all members [Valaris] #define MAX_GUILDEXPLUSION 32 #define MAX_GUILDALLIANCE 16 -#define MAX_GUILDSKILL 8 +#define MAX_GUILDSKILL 15 // increased max guild skills because of new skills [Sara-chan] #define MAX_GUILDCASTLE 24 // increased to include novice castles [Valaris] #define MAX_GUILDLEVEL 50 @@ -87,7 +87,7 @@ struct s_pet { int account_id; int char_id; int pet_id; - short class; + short class_; short level; short egg_id;//pet egg id short equip;//pet equip name_id @@ -105,7 +105,7 @@ struct mmo_charstatus { int base_exp,job_exp,zeny; - short class; + short class_; short status_point,skill_point; int hp,max_hp,sp,max_sp; short option,karma,manner; @@ -135,14 +135,14 @@ struct storage { int account_id; short storage_status; short storage_amount; - struct item storage[MAX_STORAGE]; + struct item storage_[MAX_STORAGE]; }; struct guild_storage { int guild_id; short storage_status; short storage_amount; - struct item storage[MAX_GUILD_STORAGE]; + struct item storage_[MAX_GUILD_STORAGE]; }; struct map_session_data; @@ -168,7 +168,7 @@ struct party { struct guild_member { int account_id, char_id; - short hair,hair_color,gender,class,lv; + short hair,hair_color,gender,class_,lv; int exp,exp_payper; short online,position; int rsv1,rsv2; @@ -237,8 +237,8 @@ struct guild_castle { int Ghp4; int Ghp5; int Ghp6; - int Ghp7; - int GID0; + int Ghp7; + int GID0; int GID1; int GID2; int GID3; diff --git a/src/txt-converter/login/GNUmakefile b/src/txt-converter/login/GNUmakefile deleted file mode 100644 index 9f34e143a..000000000 --- a/src/txt-converter/login/GNUmakefile +++ /dev/null @@ -1,11 +0,0 @@ -all: login-converter -sql: login-converter - -COMMON_OBJ = ../../common/core.o ../../common/socket.o ../../common/timer.o ../../common/db.o ../../common/malloc.o -COMMON_H = ../../common/core.h ../../common/socket.h ../../common/timer.h ../../common/mmo.h ../../common/version.h ../../common/db.h ../../common/malloc.h - -login-converter: login-converter.o ../../login_sql/md5calc.o ../../login_sql/strlib.o $(COMMON_OBJ) - $(CC) -o ../../../$@ $^ $(LIB_S) -login-converter.o: login-converter.c ../../login_sql/login.h ../../login_sql/md5calc.h ../../login_sql/strlib.h $(COMMON_H) -clean: - rm -f *.o ../../../login-converter diff --git a/src/txt-converter/login/Makefile b/src/txt-converter/login/Makefile index 9f34e143a..7158931d0 100644 --- a/src/txt-converter/login/Makefile +++ b/src/txt-converter/login/Makefile @@ -1,11 +1,12 @@ all: login-converter sql: login-converter -COMMON_OBJ = ../../common/core.o ../../common/socket.o ../../common/timer.o ../../common/db.o ../../common/malloc.o -COMMON_H = ../../common/core.h ../../common/socket.h ../../common/timer.h ../../common/mmo.h ../../common/version.h ../../common/db.h ../../common/malloc.h +COMMON_OBJ = ../../common/obj/core.o ../../common/obj/socket.o ../../common/obj/timer.o ../../common/obj/grfio.o ../../common/obj/db.o ../../common/obj/lock.o ../../common/obj/nullpo.o ../../common/obj/malloc.o ../../common/obj/showmsg.o ../../common/obj/strlib.o -login-converter: login-converter.o ../../login_sql/md5calc.o ../../login_sql/strlib.o $(COMMON_OBJ) +COMMON_H = ../../common/core.h ../../common/socket.h ../../common/timer.h ../../common/mmo.h ../../common/version.h ../../common/db.h ../../common/malloc.h ../../common/strlib.h + +login-converter: login-converter.o ../../login_sql/md5calc.o $(COMMON_OBJ) $(CC) -o ../../../$@ $^ $(LIB_S) -login-converter.o: login-converter.c ../../login_sql/login.h ../../login_sql/md5calc.h ../../login_sql/strlib.h $(COMMON_H) +login-converter.o: login-converter.c ../../login_sql/login.h ../../login_sql/md5calc.h $(COMMON_H) clean: rm -f *.o ../../../login-converter diff --git a/src/txt-converter/login/login-converter.c b/src/txt-converter/login/login-converter.c index a277ca949..d301e8db3 100644 --- a/src/txt-converter/login/login-converter.c +++ b/src/txt-converter/login/login-converter.c @@ -40,7 +40,7 @@ struct { int sex,delflag; } auth_fifo[AUTH_FIFO_SIZE]; int auth_fifo_pos=0; -struct { +struct auth_dat_ { int account_id, sex; char userid[24], pass[24], lastlogin[24]; int logincount; @@ -72,7 +72,7 @@ char db_server_logindb[32] = "ragnarok"; int isGM(int account_id) { struct gm_account *p; - p = numdb_search(gm_account_db,account_id); + p = (struct gm_account*)numdb_search(gm_account_db,account_id); if( p == NULL) return 0; return p->level; @@ -95,7 +95,7 @@ int read_gm_account() if(line[0] == '/' || line[1] == '/' || line[2] == '/') continue; - p=malloc(sizeof(struct gm_account)); + p = (struct gm_account*)malloc(sizeof(struct gm_account)); if(p==NULL){ printf("gm_account: out of memory!\n"); exit(0); @@ -145,7 +145,7 @@ int mmo_auth_init(void) fp=fopen("save/account.txt","r"); - auth_dat=malloc(sizeof(auth_dat[0])*256); + auth_dat = (struct auth_dat_*)malloc(sizeof(auth_dat[0])*256); auth_max=256; if(fp==NULL) return 0; @@ -234,6 +234,10 @@ int login_config_read(const char *cfgName){ strcpy(db_server_logindb, w2); printf ("set db_server_logindb : %s\n",w2); } + //support the import command, just like any other config + else if(strcmpi(w1,"import")==0){ + login_config_read(w2); + } } fclose(fp); printf ("End reading interserver configuration...\n"); diff --git a/src/webserver/Changelog.txt b/src/webserver/Changelog.txt deleted file mode 100644 index e4d38bac0..000000000 --- a/src/webserver/Changelog.txt +++ /dev/null @@ -1,3 +0,0 @@ -Date Added -12/3 - * Creation of eAthena Web Server v2 [MC Cameri]
\ No newline at end of file diff --git a/src/webserver/Makefile b/src/webserver/Makefile index 000754036..077b39980 100644 --- a/src/webserver/Makefile +++ b/src/webserver/Makefile @@ -1,32 +1,20 @@ -CC = gcc -pipe -MAKE = make -OPT = -g -O2 -ffast-math - -ifeq ($(findstring CYGWIN,$(PLATFORM)), CYGWIN) -CFLAGS = $(OPT) -Wall -I../common -else -CFLAGS = $(OPT) -Wall -I../common -endif - -OBJ = main.o webserver.o ../common/showmsg.o -LINKOBJ = main.o webserver.o ../common/showmsg.o - -all: clean webserver run +all: + #Generate framework... + $(CC) -c parse.c + $(CC) -c generate.c + $(CC) -c htmlstyle.c + $(CC) -c logs.c + + #Generate "pages"... + cd pages && $(CC) -c about.c && cd .. + cd pages && $(CC) -c sample.c && cd .. + cd pages && $(CC) -c notdone.c && cd .. + + #Building the server... + $(CC) -o webserver main.c parse.o generate.o htmlstyle.o \ + logs.o pages/about.o pages/sample.o pages/notdone.o clean: - rm -f *.o webserver.exe ../common/showmsg.o - -webserver: main.o webserver.o ../common/showmsg.o - $(CC) $(OPT) -o "Webserver.exe" $(OBJ) - -main.o: main.c - $(CC) $(OPT) -c main.c -o main.o $(CFLAGS) - -webserver.o: webserver.c - $(CC) $(OPT) -c webserver.c -o webserver.o $(CFLAGS) - -../common/showmsg.o: ../common/showmsg.c - $(CC) $(OPT) -c ../common/showmsg.c -o ../common/showmsg.o $(CFLAGS) - -run: - ./webserver + rm -f *.o + rm -f pages/*.o + rm -f webserver diff --git a/src/webserver/Makefile.win b/src/webserver/Makefile.win deleted file mode 100644 index 65cf676ad..000000000 --- a/src/webserver/Makefile.win +++ /dev/null @@ -1,35 +0,0 @@ -# Project: Webserver -# Makefile created by Dev-C++ 4.9.8.0 - -CPP = g++.exe -D__DEBUG__ -CC = gcc.exe -D__DEBUG__ -WINDRES = windres.exe -RES = -OBJ = main.o webserver.o ../common/showmsg.o $(RES) -LINKOBJ = main.o webserver.o ../common/showmsg.o $(RES) -LIBS = -L"C:/Program Files/Dev-Cpp/lib" -L"C:/cygwin/lib" -INCS = -I"C:/Program Files/Dev-Cpp/include" -I"C:/cygwin/usr/include" -I"C:/cygwin/usr/include/mingw" -CXXINCS = -I"C:/Program Files/Dev-Cpp/include/c++" -I"C:/Program Files/Dev-Cpp/include/c++/mingw32" -I"C:/Program Files/Dev-Cpp/include/c++/backward" -I"C:/Program Files/Dev-Cpp/include" -I"C:/cygwin/usr/include/c++/3.3.1" -BIN = webserver.exe -CXXFLAGS = $(CXXINCS) -pg -g3 -CFLAGS = $(INCS) -pg -g3 - -.PHONY: all all-before all-after clean clean-custom - -all: all-before webserver.exe all-after - - -clean: clean-custom - rm -f $(OBJ) $(BIN) - -$(BIN): $(LINKOBJ) - $(CC) $(LINKOBJ) -o "webserver.exe" $(LIBS) - -main.o: main.c - $(CC) -c main.c -o main.o $(CFLAGS) - -webserver.o: webserver.c - $(CC) -c webserver.c -o webserver.o $(CFLAGS) - -../common/showmsg.o: ../common/showmsg.c - $(CC) -c ../common/showmsg.c -o ../common/showmsg.o $(CFLAGS) diff --git a/src/webserver/WEBSER~1.layout b/src/webserver/WEBSER~1.layout deleted file mode 100644 index 49854196f..000000000 --- a/src/webserver/WEBSER~1.layout +++ /dev/null @@ -1,24 +0,0 @@ -[Editors] -Focused=-1 -Order=-1,0 -[Editor_0] -Open=1 -Top=0 -CursorCol=5 -CursorRow=30 -TopLine=1 -LeftChar=1 -[Editor_1] -Open=1 -Top=0 -CursorCol=1 -CursorRow=35 -TopLine=16 -LeftChar=1 -[Editor_2] -Open=1 -Top=1 -CursorCol=14 -CursorRow=4 -TopLine=1 -LeftChar=1 diff --git a/src/webserver/Webserver.dev b/src/webserver/Webserver.dev deleted file mode 100644 index 5bbb3a08c..000000000 --- a/src/webserver/Webserver.dev +++ /dev/null @@ -1,97 +0,0 @@ -[Project] -FileName=Webserver.dev -Name=Webserver -UnitCount=5 -Type=1 -Ver=1 -ObjFiles= -Includes= -Libs= -PrivateResource= -ResourceIncludes= -MakeIncludes= -Compiler= -CppCompiler= -Linker= -IsCpp=0 -Icon= -ExeOutput= -ObjectOutput= -OverrideOutput=1 -OverrideOutputName=webserver.exe -HostApplication= -Folders=common -CommandLine= -IncludeVersionInfo=0 -SupportXPThemes=0 -CompilerSet=1 -CompilerSettings=000000000000000000 - -[Unit1] -FileName=main.c -CompileCpp=0 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd=$(CC) -c main.c -o main.o webserver.o $(CFLAGS) - -[VersionInfo] -Major=0 -Minor=1 -Release=1 -Build=1 -LanguageID=1033 -CharsetID=1252 -CompanyName= -FileVersion= -FileDescription=Developed using the Dev-C++ IDE -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion= -AutoIncBuildNr=0 - -[Unit2] -FileName=webserver.c -CompileCpp=0 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=1 -BuildCmd=$(CC) -c webserver.c -o webserver.o $(CFLAGS) - -[Unit3] -FileName=webserver.h -CompileCpp=0 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit4] -FileName=..\common\showmsg.c -CompileCpp=0 -Folder=common -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit5] -FileName=..\common\showmsg.h -CompileCpp=0 -Folder=common -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - diff --git a/src/webserver/Webserver.layout b/src/webserver/Webserver.layout deleted file mode 100644 index b99312289..000000000 --- a/src/webserver/Webserver.layout +++ /dev/null @@ -1,38 +0,0 @@ -[Editors] -Focused=0 -Order=0,2,1,-1 -[Editor_0] -Open=1 -Top=1 -CursorCol=55 -CursorRow=128 -TopLine=95 -LeftChar=1 -[Editor_1] -Open=1 -Top=0 -CursorCol=25 -CursorRow=113 -TopLine=92 -LeftChar=1 -[Editor_2] -Open=1 -Top=0 -CursorCol=1 -CursorRow=21 -TopLine=1 -LeftChar=1 -[Editor_3] -Open=0 -Top=0 -CursorCol=20 -CursorRow=2 -TopLine=1 -LeftChar=1 -[Editor_4] -Open=0 -Top=0 -CursorCol=20 -CursorRow=1 -TopLine=1 -LeftChar=1 diff --git a/src/webserver/conf/webserver-athena.conf b/src/webserver/conf/webserver-athena.conf deleted file mode 100644 index 6f84aa133..000000000 --- a/src/webserver/conf/webserver-athena.conf +++ /dev/null @@ -1,36 +0,0 @@ -############################################################# -# ______ __ __ # -# /\ _ \/\ \__/\ \ # -# __\ \ \L\ \ \ ,_\ \ \___ __ ___ __ # -# /'__`\ \ __ \ \ \/\ \ _ `\ /'__`\/' _ `\ /'__`\ # -# /\ __/\ \ \/\ \ \ \_\ \ \ \ \/\ __//\ \/\ \/\ \L\.\_ # -# \ \____\\ \_\ \_\ \__\\ \_\ \_\ \____\ \_\ \_\ \__/.\_\ # -# \/____/ \/_/\/_/\/__/ \/_/\/_/\/____/\/_/\/_/\/__/\/_/ # -# eAthena Web Server (Second Edition) # -# by MC Cameri # -# ------------------------------------------------------- # -# -Website/Forum- # -# http://eathena.deltaanime.net/ # -# -Download URL- # -# http://eathena.systeminplace.net/ # -# -IRC Channel- # -# irc://irc.deltaanime.net/#athena # -############################################################# - -// Display the eAthena Logo at startup? -show_title: 1 - -//Web Server Port -port: 81 - -//Web Server Password -password: juan16 - -//Page Header -header: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - -//Document index -document_index: index.xhtml - -//Send favorite icon if provided? -favicon: yes diff --git a/src/webserver/doc/API.txt b/src/webserver/doc/API.txt new file mode 100644 index 000000000..c80f7bd44 --- /dev/null +++ b/src/webserver/doc/API.txt @@ -0,0 +1,50 @@ +Here's the webserver API, so you can work on the webserver. + +My personal goal is to make this interface simple, so that coding it +will be like coding in some scripting language... + + + +char *get_param(char in_string[500], char swhat[500]); + +This function simply returns various data from the query string. + *Pass get_param NOTHING longer than 500 in length! + + What do I pass where in_string is? + The query string. + + What do I pass where swhat is? + One of two things... + Either 0 for the path of the 'page' + or you can pass it the param you wish to lookup. + + + + + + +char *get_query(char *inquery); + +This function simply returns a query string from the raw server request. +This is used once in main, I doubt you'll need it. + + + + + +void web_send(int sockin, char *in_data); + +Super easy way of sending data to a webpage! +Simply put in the socket name and then the data. + + Ex: + web_send(socket, "I like cheese!\n"); + + + + +char *html_header(char* title); +Easy way to print the eAthena header for the server. + + Ex: + web_send(sockethere, html_header("About")); diff --git a/src/webserver/doc/README b/src/webserver/doc/README new file mode 100644 index 000000000..0e94ff2ae --- /dev/null +++ b/src/webserver/doc/README @@ -0,0 +1,11 @@ +This readme is intended for the programmers of eAthena. + +This webserver's apis are in API.txt. + +To make this simple, generate.c should handle most of the work this sever does +in terms of what people see. + +When a request is made the server shoots it off to generate.c. + +You are welcome to create more functions used by generate.c to generate pages +though, so don't feel limited by that one file. diff --git a/src/webserver/generate.c b/src/webserver/generate.c new file mode 100644 index 000000000..ad050db4c --- /dev/null +++ b/src/webserver/generate.c @@ -0,0 +1,38 @@ + +void generate_page(char password[25], int sock_in, char *query, char *ip) +{ + char *page = get_param(query, 0); + char *ppass = get_param(query, "password"); + + + if ( (ppass == 0) || (strcmp(password, ppass) != 0) ) + { + web_send(sock_in, html_header("Enter your password")); + web_send(sock_in, "<H1>NOT LOGGED IN!</H1><form action=\"/\" method=\"GET\">\n"); + web_send(sock_in, "Enter your password:<br>\n<input type=\"text\" name=\"password\">\n"); + web_send(sock_in, "<input type=\"submit\" value=\"Login\">\n"); + } + else + { + + + //To make this simple, we will have a bunch of if statements + //that then shoot out data off into functions. + + + //The 'index' + if ( strcmp(page, "/") == 0 ) + generate_notdone(sock_in, query, ip); + + + //About page: + if ( strcmp(page, "/about.html") == 0 ) + generate_about(sock_in, query, ip); + + + //Test page: + if ( strcmp(page, "/testing/") == 0 ) + generate_sample(sock_in, query, ip); + + } +} diff --git a/src/webserver/htmlstyle.c b/src/webserver/htmlstyle.c new file mode 100644 index 000000000..c3a4b927a --- /dev/null +++ b/src/webserver/htmlstyle.c @@ -0,0 +1,51 @@ +char output[10000]; + +char *html_header(char *title) +{ + memset(output, 0x0, 10000); + char *text = "<body text=\"#000000\" bgcolor=\"#939393\" link=\"#0033FF\">\n" + "<br><table width=\"92%\" cellspacing=\"1\" cellpadding=\"0\" border=\"0\"\n" + "align=\"center\" class=\"bordercolor\"><tbody><tr><td class=\"bordercolor\" width=\"100%\">\n" + "<table bgcolor=\"#ffffff\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\">\n" + "<tbody><tr><td><table border=\"0\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#ffffff\">\n" + "<tbody><tr><img src=\"http://eathena.sourceforge.net/athena.jpg\" alt=\"Athena\">\n" + "<td bgcolor=\"#ffffff\"></td></tr></tbody></table></td></tr></tbody></table>\n" + "</td></tr><tr align=\"left\"><td class=\"bordercolor\"><table bgcolor=\"#c6c6c6\" width=\"100%\" cellspacing=\"0\"\n" + "cellpadding=\"0\" style=\"text-align: left; margin-right: auto; margin-left: 0px;\">\n"; + "<tbody><tr><td width=\"100%\" align=\"center\"><table border=\"0\" width=\"100%\" cellpadding=\"3\"\n" + "cellspacing=\"0\" bgcolor=\"#c6c6c6\" align=\"center\"><tbody><tr>" + "<td valign=\"middle\" bgcolor=\"#c6c6c6\" align=\"center\"><a href=\"/cgi-bin/forum/YaBB.cgi\">" + "<span style=\"text-decoration: underline;\"><span style=\"font-weight: bold;\">\n" + "To the Forum</span></span></a><br></td></tr></tbody></table></td></tr></tbody>\n" + "</table></td></tr><tr><td class=\"bordercolor\" align=\"center\">\n" + "<table bgcolor=\"#ffffff\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n" + "<tbody><tr><td width=\"100%\" align=\"center\"><table border=\"0\" width=\"100%\" cellpadding=\"5\"\n" + "cellspacing=\"0\" bgcolor=\"#ffffff\" align=\"center\"><tbody><tr>\n" + "<td valign=\"middle\" bgcolor=\"#ffffff\" align=\"center\"><font size=\"2\" color=\"#6e94b7\">\n" + "<b>Athena</b> « Portal »</font></td></tr></tbody></table></td></tr></tbody>" + "</table></td></tr></tbody></table>\n"; + + sprintf(output, "<title>%s</title>\n%s\n", title, text); + + return output; +} + + + +char *html_start_form(char *location, char *action) +{ + memset(output, 0x0, 10000); + sprintf(output, "<form action=\"%s\" method=\"%s\">", location, action); + return output; + + +} + + +char *html_end_forum(void) +{ + return "</form>"; +} + + + diff --git a/src/webserver/logs.c b/src/webserver/logs.c new file mode 100644 index 000000000..405b4882b --- /dev/null +++ b/src/webserver/logs.c @@ -0,0 +1,8 @@ +#include <time.h> + +void log_visit(char *query, char *ip) +{ + time_t timer; + timer=time(NULL); + printf("%s - \"%s\" - %s", ip, query, asctime(localtime(&timer))); +} diff --git a/src/webserver/main.c b/src/webserver/main.c index 915d71b6d..59362558e 100644 --- a/src/webserver/main.c +++ b/src/webserver/main.c @@ -1,144 +1,142 @@ -/****************************************************************************** - # ______ __ __ # - # /\ _ \/\ \__/\ \ # - # __\ \ \L\ \ \ ,_\ \ \___ __ ___ __ # - # /'__`\ \ __ \ \ \/\ \ _ `\ /'__`\/' _ `\ /'__`\ # - # /\ __/\ \ \/\ \ \ \_\ \ \ \ \/\ __//\ \/\ \/\ \L\.\_ # - # \ \____\\ \_\ \_\ \__\\ \_\ \_\ \____\ \_\ \_\ \__/.\_\ # - # \/____/ \/_/\/_/\/__/ \/_/\/_/\/____/\/_/\/_/\/__/\/_/ # - # eAthena Web Server (Second Edition) # - # by MC Cameri # - # ------------------------------------------------------- # - # -Website/Forum- # - # http://eathena.deltaanime.net/ # - # -Download URL- # - # http://eathena.systeminplace.net/ # - # -IRC Channel- # - # irc://irc.deltaanime.net/#athena # - ******************************************************************************/ +/*************************************************************************** + description + ------------------- + author : (C) 2004 by Michael J. Flickinger + email : mjflick@cpan.org + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + #include <stdio.h> #include <stdlib.h> -#include <strings.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/wait.h> #include <signal.h> -#include <unistd.h> -#include <errno.h> -#include "../common/showmsg.h" -#include "webserver.h" +#define BLOG 10 -char ws_password[17]; -char ws_header[128]; +char *header = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"; +char recvin[500], password[25]; +int s_port; -#define WEB_CONF "conf/webserver-athena.conf" -#define MAX_CONNECTIONS 10 -#define HOME "home/" - -struct config config; +void sigchld_handler(int s) +{ + while(wait(NULL) > 0); +} -int main(int argc, char *argv[]) +int main(int argc, char **argv) { - int server_fd, client_fd; + if (argc < 3) + { + printf("eAthena Web Server\n"); + printf("usage: %s [password] [port]\n", argv[0]); + exit(0); + } + + s_port = atoi(argv[2]); + + if ((s_port < 1) || (s_port > 65534)) + { + printf("Error: The port you choose is not valid port.\n"); + exit(0); + } + + if (strlen(argv[1]) > 25) + { + printf("Error: Your password is too long.\n"); + printf("It must be shorter than 25 characters.\n"); + exit(0); + } + + memset(password, 0x0, 25); + memcpy(password, argv[1], strlen(argv[1])); + + int sockfd, new_fd; + struct sockaddr_in my_addr; + struct sockaddr_in their_addr; int sin_size; - struct sockaddr_in server_addr; - struct sockaddr_in client_addr; + struct sigaction sa; - char recvin[1024]; - char path[1024]; - char line[1024]; - int optval = 1; - if (ws_config_read(WEB_CONF)) exit(0); - if (config.show_title) - ws_display_title(); - else - printf("eAthena Web Server (Second Edition)\n"); - if (strcmpEx(ws_password,"webpass")==0) - ShowWarning("You are using the default password (webpass), we highly " - "recommend\n that you change it.\n"); - else if (strstr(ws_password,"webpass")) - ShowWarning("Your password should not contain \"webpass\" in it, it is" - " highly\n recommended that you change it.\n"); - printf("Web Server Password: %s\n",ws_password); - printf("Web Server Port: %d\n",config.port); - - if ((server_fd = socket(AF_INET, SOCK_STREAM,0)) == -1) { - ShowError("In main() -> Could not open socket.\n"); - return 1; + + int yes=1; + + if ((sockfd = socket(AF_INET, SOCK_STREAM,0)) == -1) + { + perror("Darn, this is broken."); + exit(0); } - if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)) == -1) { - ShowError("In main() -> Could not set socket options.\n"); - return 1; + + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) + { + perror("Error... :-("); } - server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(config.port); - server_addr.sin_addr.s_addr = INADDR_ANY; - memset(&(server_addr.sin_zero), '\0', 8); - - if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0) { - snprintf(tmp_output,sizeof(tmp_output),"In main() -> Could not bind to port number: %d\n",config.port); - ShowError(tmp_output); - return 1; + + //Now we know we have a working socket. :-) + + my_addr.sin_family = AF_INET; + my_addr.sin_port = htons(s_port); + my_addr.sin_addr.s_addr = INADDR_ANY; + memset(&(my_addr.sin_zero), '\0', 8); + + if ( bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) + { + perror("can not bind to this port"); + exit(0); } - if (listen(server_fd, MAX_CONNECTIONS) < 0) { - snprintf(tmp_output,sizeof(tmp_output),"In main() -> Could not listen on port number: %d\n",config.port); - ShowError(tmp_output); - return 1; + if ( listen(sockfd, BLOG) == -1) + { + perror("can not listen on port"); + exit(0); } - sa.sa_handler = ws_sigchld_handler; + sa.sa_handler = sigchld_handler; + sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - if (sigaction(SIGCHLD, &sa, NULL) < 0) { - ShowError("In main() -> Invalid sigaction.\n"); - return 1; + if (sigaction(SIGCHLD, &sa, NULL) == -1) + { + perror("sigaction sucks"); + exit(0); } - ShowInfo("eAthena Web Server is now listening for incoming connections.\n"); + + printf("The eAthena webserver is up and listening on port %i.\n", s_port); while(1) { sin_size = sizeof(struct sockaddr_in); - client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &sin_size); + new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); if (!fork()) { - close(server_fd); + close(sockfd); memset(recvin, 0x0, 500); - recv(client_fd, recvin, 500, 0); - char *html_output; - int count = 0; - if (sscanf(recvin,"GET %[a-zA-Z_-.+\%#@~] %*[^\n]",path)==1) { - FILE *fp; - strcpy(tmp_output,HOME); - strcat(tmp_output,path); - fp = fopen(tmp_output,"r+"); - if (fp==NULL) { - send(client_fd,"File not found",strlen("File not found"), 0); - close(client_fd); - } - memset(tmp_output,0x0,strlen(tmp_output)); - html_output = (char*)malloc(sizeof(char)*2); - while (fgets(line,1023,fp)) { - html_output = (char*)realloc(sizeof(html_output)+(sizeof(char)*count)); - strcat(html_output,line); - printf(line); - } - send(client_fd,tmp_output,sizeof(tmp_output),0); - fclose(fp); - } - // send(client_fd, ws_header, strlen(ws_header), 0); - // generate_page(password, client_fd, get_query(recvin), inet_ntoa(client_addr.sin_addr)); - // log_visit(get_query(recvin), inet_ntoa(client_addr.sin_addr)); - close(client_fd); + recv(new_fd, recvin, 500, 0); + send(new_fd, header, strlen(header), 0); + generate_page(password, new_fd, get_query(recvin), inet_ntoa(their_addr.sin_addr)); + log_visit(get_query(recvin), inet_ntoa(their_addr.sin_addr)); + + close(new_fd); exit(0); } - close(client_fd); + close(new_fd); } + return 0; } diff --git a/src/webserver/pages/about.c b/src/webserver/pages/about.c new file mode 100644 index 000000000..2b0002ad8 --- /dev/null +++ b/src/webserver/pages/about.c @@ -0,0 +1,6 @@ +void generate_about(int sock_in, char *query, char *ip) +{ +//printf("%s", html_header("About")); + web_send(sock_in, html_header("About")); + web_send(sock_in, "<center>eAthena Web Server!</center>\n"); +} diff --git a/src/webserver/pages/notdone.c b/src/webserver/pages/notdone.c new file mode 100644 index 000000000..a6492e361 --- /dev/null +++ b/src/webserver/pages/notdone.c @@ -0,0 +1,5 @@ +void generate_notdone(int sock_in, char *query, char *ip) +{ + web_send(sock_in, "<title>Not here!</title>\n"); + web_send(sock_in, "<h2><center>This page/feature is not done yet.</center>\n</h2>"); +} diff --git a/src/webserver/pages/sample.c b/src/webserver/pages/sample.c new file mode 100644 index 000000000..be900a1bf --- /dev/null +++ b/src/webserver/pages/sample.c @@ -0,0 +1,24 @@ + + +void generate_sample(int sock_in, char *query, char *ip) +{ + + char *name = get_param(query, "name"); + + web_send(sock_in, "<title>SAMPLE</title>\n"); + + + //If a name was not entered... + if ( name == '\0' ) + { + web_send(sock_in, "<form action=\"/testing/\" method=\"GET\">\n"); + web_send(sock_in, "<input type=\"text\" name=\"name\">\n"); + web_send(sock_in, "<input type=\"submit\">\n"); + } + else + { + web_send(sock_in, "Your name is: "); + web_send(sock_in, get_param(query, "name")); + } +printf("OK!\n"); +} diff --git a/src/webserver/parse.c b/src/webserver/parse.c new file mode 100644 index 000000000..8e54a81de --- /dev/null +++ b/src/webserver/parse.c @@ -0,0 +1,135 @@ +#include <stdlib.h> + +char filtered_query[2000]; +char rdata[500]; +char param_n[500]; +char param_d[500]; + + +char *get_query(char *inquery) +{ + memset(filtered_query, 0x0, 2000); + sscanf(inquery, "GET %s %[$]", filtered_query); + return(filtered_query); +} + +void web_send(int sockin, char *in_data) +{ + send(sockin, in_data, strlen(in_data), 0); +} + + +//THIS IS BAD CODE BE CAREFULL WITH IT! +//Watch out for buffer overflow... +//When using please make sure to check the string size. + +//Also note: +//I take no pride in this code, it is a really bad way of doing this... +char *get_param(char in_string[500], char swhat[500]) +{ + int i = 0; + int marker, iswitch, pint, dint; + char flux[500]; + memset(flux, 0x0, 500); + + //Get the path of out "page" + if (swhat == 0) + { + //while i is not equal to array size + while (i != 500) + { + //if there is a question mark, halt! + if (in_string[i] == '?') + { + i = 499; + } + else + rdata[i] = in_string[i]; + + i++; + } + return rdata; + } + else //so, we want a param... + { + //calculate where param begins + while (i != 500) + { + if (in_string[i] == '?') + { + marker = i + 1; + i = 499; + } + i++; + } + + i = 0; + + //keep morons from trying to crash this + if ((marker > 500)||(marker < 1)) + marker = 500; + + while(marker != 500) + { + if ((in_string[marker] != '&') && (in_string[marker] != '\0')) + { + flux[i] = in_string[marker]; + i++; + } + else + { + + //we have a param, now we must dig through it + + //clear temp vars + memset(param_n, 0x0, 500); + memset(param_d, 0x0, 500); + iswitch = 0; + pint = 0; + dint = 0; + i = 0; + + //split result into param_n and param_d + while(i != 500) + { + if ( (flux[i] != '=') && (flux[i] != '\0') ) + { + if (iswitch == 0) + { + param_n[pint] = flux[i]; + pint++; + } + else + { + param_d[dint] = flux[i]; + dint++; + } + } + else + { + iswitch = 1; + } + if (flux[i] == '\0') + i = 499; + + i++; + } + + if ( strcmp(param_n, swhat) == 0 ) + { + return param_d; + } + + i = 0; + } + + if (in_string[marker] == '\0') + { + marker = 499; + } + marker++; + } + return 0; + } +} + diff --git a/src/webserver/webserver.c b/src/webserver/webserver.c deleted file mode 100644 index 0169cd028..000000000 --- a/src/webserver/webserver.c +++ /dev/null @@ -1,136 +0,0 @@ -/****************************************************************************** - # ______ __ __ # - # /\ _ \/\ \__/\ \ # - # __\ \ \L\ \ \ ,_\ \ \___ __ ___ __ # - # /'__`\ \ __ \ \ \/\ \ _ `\ /'__`\/' _ `\ /'__`\ # - # /\ __/\ \ \/\ \ \ \_\ \ \ \ \/\ __//\ \/\ \/\ \L\.\_ # - # \ \____\\ \_\ \_\ \__\\ \_\ \_\ \____\ \_\ \_\ \__/.\_\ # - # \/____/ \/_/\/_/\/__/ \/_/\/_/\/____/\/_/\/_/\/__/\/_/ # - # eAthena Web Server (Second Edition) # - # by MC Cameri # - # ------------------------------------------------------- # - # -Website/Forum- # - # http://eathena.deltaanime.net/ # - # -Download URL- # - # http://eathena.systeminplace.net/ # - # -IRC Channel- # - # irc://irc.deltaanime.net/#athena # - ******************************************************************************/ - -#include <stdio.h> -#include <strings.h> -#include "../common/showmsg.h" -#include "webserver.h" - -char ws_password[17] = "pass"; -char ws_header[128] = {'\0'}; - -/* Displays the eAthena Logo */ -void ws_display_title(void) -{ - printf("\033[2J"); - printf("\033[37;44m (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)\033[K\033[0m\n"); - printf("\033[0;44m (\033[1;33m (c)2004 eAthena Development Team presents \033[0;44m)\033[K\033[0m\n"); - printf("\033[0;44m (\033[1m ______ __ __ \033[0;44m)\033[K\033[0m\n"); - printf("\033[0;44m (\033[1m /\\ _ \\/\\ \\__/\\ \\ \033[0;44m)\033[K\033[0m\n"); - printf("\033[0;44m (\033[1m __\\ \\ \\_\\ \\ \\ ,_\\ \\ \\___ __ ___ __ \033[0;44m)\033[K\033[0m\n"); - printf("\033[0;44m (\033[1m /'__`\\ \\ __ \\ \\ \\/\\ \\ _ `\\ /'__`\\/' _ `\\ /'__`\\ \033[0;44m)\033[K\033[0m\n"); - printf("\033[0;44m (\033[1m /\\ __/\\ \\ \\/\\ \\ \\ \\_\\ \\ \\ \\ \\/\\ __//\\ \\/\\ \\/\\ \\_\\.\\_ \033[0;44m)\033[K\033[0m\n"); - printf("\033[0;44m (\033[1m \\ \\____\\\\ \\_\\ \\_\\ \\__\\\\ \\_\\ \\_\\ \\____\\ \\_\\ \\_\\ \\__/.\\_\\ \033[0;44m)\033[K\033[0m\n"); - printf("\033[0;44m (\033[1m \\/____/ \\/_/\\/_/\\/__/ \\/_/\\/_/\\/____/\\/_/\\/_/\\/__/\\/_/ \033[0;44m)\033[K\033[0m\n"); - printf("\033[0;44m (\033[1m _ _ _ _ _ _ _ _ _ _ _ _ _ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char - printf("\033[0;44m (\033[1m / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char - printf("\033[0;44m (\033[1m ( e | n | g | l | i | s | h ) ( A | t | h | e | n | a ) \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char - printf("\033[0;44m (\033[1m \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char - printf("\033[0;44m (\033[1m \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) - printf("\033[0;44m (\033[1;33m Advanced Fusion Maps (c) 2003-2004 The Fusion Project \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) - printf("\033[37;44m (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)\033[K\033[0m\n\n"); // reset color -} -/* Returns a boolean value given character string */ -int ws_config_switch(const char *str) { - if (strcmpEx(str, "on") == 0 || strcmpEx(str, "yes") == 0 || - strcmpEx(str, "oui") == 0 || strcmpEx(str, "ja") == 0 || - strcmpEx(str, "si") == 0 || strcmpEx(str,"true") == 0) - return 1; - if (strcmpEx(str, "off") == 0 || strcmpEx(str, "no") == 0 || - strcmpEx(str, "non") == 0 || strcmpEx(str, "nein") == 0 || - strcmpEx(str, "false") == 0) - return 0; - return atoi(str); -} - -/* Reads the eAthena Web Server's configuration file */ -int ws_config_read(const char *cfgName) -{ - int i; - char line[1024],w1[1024],w2[1024],temp[1024]; - FILE *fp; - - /* Default values */ - config.show_title=0; - config.port=80; - - - fp=fopen(cfgName,"r"); - if(fp==NULL){ - snprintf(temp,sizeof(temp),"Could not open \033[1;29m%s\033[0;0m, file not found.\n",cfgName); - ShowMessage(temp,MSG_ERROR); - return 1; - } - while(fgets(line,1020,fp)){ - const struct { - char str[128]; - int *val; - } data[] ={ - //List of variables - { "show_title", &config.show_title }, - { "port", &config.port }, - }; - - if((line[0] == '/' && line[1] == '/') || (line[0]=='#') || - (sscanf(line,"%1023[^:]:%1023[^\n]",w1,w2) !=2)) - continue; - for(i=0;i<sizeof(data)/(sizeof(data[0]));i++) { - if(strcmpEx(w1,data[i].str)==0){ - *data[i].val=ws_config_switch(w2); - break; - } - } - if(strcmpEx(w1,"import")==0) { - ws_config_read(w2); - continue; - } - if(strcmpEx(w1,"password")==0) { - if (strlen(w2)>16) { - ShowError("The Web Server password is too long, maximum passwor" - "d length is 16 characters.\n"); - return 1; - } - strcpy(ws_password,w2); - continue; - } - if(strcmpEx(w1,"header")==0) { - if (strlen(w2)>127) { - ShowError("The Web Server header is too long, maximum header" - "d length is 127 characters.\n"); - return 1; - } - strcpy(ws_header,w2); - continue; - } - } - fclose(fp); - - //Correct values - if(config.show_title < 0) - config.show_title = 0; - if(config.port < 1 || config.port > 65534) - config.port=80; - - return 0; -} - -void ws_sigchld_handler(int s) -{ - while(wait(NULL) > 0); -} diff --git a/src/webserver/webserver.h b/src/webserver/webserver.h deleted file mode 100644 index 84ef02b62..000000000 --- a/src/webserver/webserver.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef WEBSERV_H_ -#define WEBSERV_H_ - -#define strcmpEx(x,y) (strcasecmp(x,y)) - -extern void ws_display_title(void); - -extern int ws_config_read(const char *cfgName); - -extern struct config { - int show_title; - int port; -} config; - -extern char ws_password[17]; //16 chars + \0 - -extern char ws_header[128]; //!? - -extern void ws_sigchld_handler(int s); - -#endif diff --git a/src/zlib/FAQ b/src/zlib/FAQ new file mode 100644 index 000000000..4f61f1094 --- /dev/null +++ b/src/zlib/FAQ @@ -0,0 +1,337 @@ + + Frequently Asked Questions about zlib + + +If your question is not there, please check the zlib home page +http://www.zlib.org which may have more recent information. +The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html + + + 1. Is zlib Y2K-compliant? + + Yes. zlib doesn't handle dates. + + 2. Where can I get a Windows DLL version? + + The zlib sources can be compiled without change to produce a DLL. + See the file win32/DLL_FAQ.txt in the zlib distribution. + Pointers to the precompiled DLL are found in the zlib web site at + http://www.zlib.org. + + 3. Where can I get a Visual Basic interface to zlib? + + See + * http://www.dogma.net/markn/articles/zlibtool/zlibtool.htm + * contrib/visual-basic.txt in the zlib distribution + * win32/DLL_FAQ.txt in the zlib distribution + + 4. compress() returns Z_BUF_ERROR. + + Make sure that before the call of compress, the length of the compressed + buffer is equal to the total size of the compressed buffer and not + zero. For Visual Basic, check that this parameter is passed by reference + ("as any"), not by value ("as long"). + + 5. deflate() or inflate() returns Z_BUF_ERROR. + + Before making the call, make sure that avail_in and avail_out are not + zero. When setting the parameter flush equal to Z_FINISH, also make sure + that avail_out is big enough to allow processing all pending input. + Note that a Z_BUF_ERROR is not fatal--another call to deflate() or + inflate() can be made with more input or output space. A Z_BUF_ERROR + may in fact be unavoidable depending on how the functions are used, since + it is not possible to tell whether or not there is more output pending + when strm.avail_out returns with zero. + + 6. Where's the zlib documentation (man pages, etc.)? + + It's in zlib.h for the moment, and Francis S. Lin has converted it to a + web page zlib.html. Volunteers to transform this to Unix-style man pages, + please contact us (zlib@gzip.org). Examples of zlib usage are in the files + example.c and minigzip.c. + + 7. Why don't you use GNU autoconf or libtool or ...? + + Because we would like to keep zlib as a very small and simple + package. zlib is rather portable and doesn't need much configuration. + + 8. I found a bug in zlib. + + Most of the time, such problems are due to an incorrect usage of + zlib. Please try to reproduce the problem with a small program and send + the corresponding source to us at zlib@gzip.org . Do not send + multi-megabyte data files without prior agreement. + + 9. Why do I get "undefined reference to gzputc"? + + If "make test" produces something like + + example.o(.text+0x154): undefined reference to `gzputc' + + check that you don't have old files libz.* in /usr/lib, /usr/local/lib or + /usr/X11R6/lib. Remove any old versions, then do "make install". + +10. I need a Delphi interface to zlib. + + See the contrib/delphi directory in the zlib distribution. + +11. Can zlib handle .zip archives? + + Not by itself, no. See the directory contrib/minizip in the zlib + distribution. + +12. Can zlib handle .Z files? + + No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt + the code of uncompress on your own. + +13. How can I make a Unix shared library? + + make clean + ./configure -s + make + +14. How do I install a shared zlib library on Unix? + + After the above, then: + + make install + + However, many flavors of Unix come with a shared zlib already installed. + Before going to the trouble of compiling a shared version of zlib and + trying to install it, you may want to check if it's already there! If you + can #include <zlib.h>, it's there. The -lz option will probably link to it. + +15. I have a question about OttoPDF. + + We are not the authors of OttoPDF. The real author is on the OttoPDF web + site: Joel Hainley, jhainley@myndkryme.com. + +16. Can zlib decode Flate data in an Adobe PDF file? + + Yes. See http://www.fastio.com/ (ClibPDF), or http://www.pdflib.com/ . + To modify PDF forms, see http://sourceforge.net/projects/acroformtool/ . + +17. Why am I getting this "register_frame_info not found" error on Solaris? + + After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib + generates an error such as: + + ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: + symbol __register_frame_info: referenced symbol not found + + The symbol __register_frame_info is not part of zlib, it is generated by + the C compiler (cc or gcc). You must recompile applications using zlib + which have this problem. This problem is specific to Solaris. See + http://www.sunfreeware.com for Solaris versions of zlib and applications + using zlib. + +18. Why does gzip give an error on a file I make with compress/deflate? + + The compress and deflate functions produce data in the zlib format, which + is different and incompatible with the gzip format. The gz* functions in + zlib on the other hand use the gzip format. Both the zlib and gzip + formats use the same compressed data format internally, but have different + headers and trailers around the compressed data. + +19. Ok, so why are there two different formats? + + The gzip format was designed to retain the directory information about + a single file, such as the name and last modification date. The zlib + format on the other hand was designed for in-memory and communication + channel applications, and has a much more compact header and trailer and + uses a faster integrity check than gzip. + +20. Well that's nice, but how do I make a gzip file in memory? + + You can request that deflate write the gzip format instead of the zlib + format using deflateInit2(). You can also request that inflate decode + the gzip format using inflateInit2(). Read zlib.h for more details. + + Note that you cannot specify special gzip header contents (e.g. a file + name or modification date), nor will inflate tell you what was in the + gzip header. If you need to customize the header or see what's in it, + you can use the raw deflate and inflate operations and the crc32() + function and roll your own gzip encoding and decoding. Read the gzip + RFC 1952 for details of the header and trailer format. + +21. Is zlib thread-safe? + + Yes. However any library routines that zlib uses and any application- + provided memory allocation routines must also be thread-safe. zlib's gz* + functions use stdio library routines, and most of zlib's functions use the + library memory allocation routines by default. zlib's Init functions allow + for the application to provide custom memory allocation routines. + + Of course, you should only operate on any given zlib or gzip stream from a + single thread at a time. + +22. Can I use zlib in my commercial application? + + Yes. Please read the license in zlib.h. + +23. Is zlib under the GNU license? + + No. Please read the license in zlib.h. + +24. The license says that altered source versions must be "plainly marked". So + what exactly do I need to do to meet that requirement? + + You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In + particular, the final version number needs to be changed to "f", and an + identification string should be appended to ZLIB_VERSION. Version numbers + x.x.x.f are reserved for modifications to zlib by others than the zlib + maintainers. For example, if the version of the base zlib you are altering + is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and + ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also + update the version strings in deflate.c and inftrees.c. + + For altered source distributions, you should also note the origin and + nature of the changes in zlib.h, as well as in ChangeLog and README, along + with the dates of the alterations. The origin should include at least your + name (or your company's name), and an email address to contact for help or + issues with the library. + + Note that distributing a compiled zlib library along with zlib.h and + zconf.h is also a source distribution, and so you should change + ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes + in zlib.h as you would for a full source distribution. + +25. Will zlib work on a big-endian or little-endian architecture, and can I + exchange compressed data between them? + + Yes and yes. + +26. Will zlib work on a 64-bit machine? + + It should. It has been tested on 64-bit machines, and has no dependence + on any data types being limited to 32-bits in length. If you have any + difficulties, please provide a complete problem report to zlib@gzip.org + +27. Will zlib decompress data from the PKWare Data Compression Library? + + No. The PKWare DCL uses a completely different compressed data format + than does PKZIP and zlib. However, you can look in zlib's contrib/blast + directory for a possible solution to your problem. + +28. Can I access data randomly in a compressed stream? + + No, not without some preparation. If when compressing you periodically + use Z_FULL_FLUSH, carefully write all the pending data at those points, + and keep an index of those locations, then you can start decompression + at those points. You have to be careful to not use Z_FULL_FLUSH too + often, since it can significantly degrade compression. + +29. Does zlib work on MVS, OS/390, CICS, etc.? + + We don't know for sure. We have heard occasional reports of success on + these systems. If you do use it on one of these, please provide us with + a report, instructions, and patches that we can reference when we get + these questions. Thanks. + +30. Is there some simpler, easier to read version of inflate I can look at + to understand the deflate format? + + First off, you should read RFC 1951. Second, yes. Look in zlib's + contrib/puff directory. + +31. Does zlib infringe on any patents? + + As far as we know, no. In fact, that was originally the whole point behind + zlib. Look here for some more information: + + http://www.gzip.org/#faq11 + +32. Can zlib work with greater than 4 GB of data? + + Yes. inflate() and deflate() will process any amount of data correctly. + Each call of inflate() or deflate() is limited to input and output chunks + of the maximum value that can be stored in the compiler's "unsigned int" + type, but there is no limit to the number of chunks. Note however that the + strm.total_in and strm_total_out counters may be limited to 4 GB. These + counters are provided as a convenience and are not used internally by + inflate() or deflate(). The application can easily set up its own counters + updated after each call of inflate() or deflate() to count beyond 4 GB. + compress() and uncompress() may be limited to 4 GB, since they operate in a + single call. gzseek() and gztell() may be limited to 4 GB depending on how + zlib is compiled. See the zlibCompileFlags() function in zlib.h. + + The word "may" appears several times above since there is a 4 GB limit + only if the compiler's "long" type is 32 bits. If the compiler's "long" + type is 64 bits, then the limit is 16 exabytes. + +33. Does zlib have any security vulnerabilities? + + The only one that we are aware of is potentially in gzprintf(). If zlib + is compiled to use sprintf() or vsprintf(), then there is no protection + against a buffer overflow of a 4K string space, other than the caller of + gzprintf() assuring that the output will not exceed 4K. On the other + hand, if zlib is compiled to use snprintf() or vsnprintf(), which should + normally be the case, then there is no vulnerability. The ./configure + script will display warnings if an insecure variation of sprintf() will + be used by gzprintf(). Also the zlibCompileFlags() function will return + information on what variant of sprintf() is used by gzprintf(). + + If you don't have snprintf() or vsnprintf() and would like one, you can + find a portable implementation here: + + http://www.ijs.si/software/snprintf/ + + Note that you should be using the most recent version of zlib. Versions + 1.1.3 and before were subject to a double-free vulnerability. + +34. Is there a Java version of zlib? + + Probably what you want is to use zlib in Java. zlib is already included + as part of the Java SDK in the java.util.zip package. If you really want + a version of zlib written in the Java language, look on the zlib home + page for links: http://www.zlib.org/ + +35. I get this or that compiler or source-code scanner warning when I crank it + up to maximally-pedantic. Can't you guys write proper code? + + Many years ago, we gave up attempting to avoid warnings on every compiler + in the universe. It just got to be a waste of time, and some compilers + were downright silly. So now, we simply make sure that the code always + works. + +36. Will zlib read the (insert any ancient or arcane format here) compressed + data format? + + Probably not. Look in the comp.compression FAQ for pointers to various + formats and associated software. + +37. How can I encrypt/decrypt zip files with zlib? + + zlib doesn't support encryption. The original PKZIP encryption is very weak + and can be broken with freely available programs. To get strong encryption, + use GnuPG, http://www.gnupg.org/ , which already includes zlib compression. + For PKZIP compatible "encryption", look at http://www.info-zip.org/ + +38. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? + + "gzip" is the gzip format, and "deflate" is the zlib format. They should + probably have called the second one "zlib" instead to avoid confusion + with the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 + correctly points to the zlib specification in RFC 1950 for the "deflate" + transfer encoding, there have been reports of servers and browsers that + incorrectly produce or expect raw deflate data per the deflate + specficiation in RFC 1951, most notably Microsoft. So even though the + "deflate" transfer encoding using the zlib format would be the more + efficient approach (and in fact exactly what the zlib format was designed + for), using the "gzip" transfer encoding is probably more reliable due to + an unfortunate choice of name on the part of the HTTP 1.1 authors. + + Bottom line: use the gzip format for HTTP 1.1 encoding. + +39. Does zlib support the new "Deflate64" format introduced by PKWare? + + No. PKWare has apparently decided to keep that format proprietary, since + they have not documented it as they have previous compression formats. + In any case, the compression improvements are so modest compared to other + more modern approaches, that it's not worth the effort to implement. + +40. Can you please sign these lengthy legal documents and fax them back to us + so that we can use your software in our product? + + No. Go away. Shoo. diff --git a/src/zlib/README b/src/zlib/README new file mode 100644 index 000000000..df95ae13f --- /dev/null +++ b/src/zlib/README @@ -0,0 +1,126 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.2 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). These documents are also available in other +formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file example.c which also tests that the library +is working correctly. Another example is given in the file minigzip.c. The +compression library itself is composed of all source files except example.c and +minigzip.c. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile. In short "make test; make install" should work for most +machines. For Unix: "./configure; make test; make install" For MSDOS, use one +of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or +descrip.mms. + +Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant +<info@winimage.com> for the Windows DLL version. The zlib home page is +http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, +please check this site to verify that you have the latest version of zlib; +otherwise get the latest version and check whether the problem still exists or +not. + +PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking +for help. + +Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available in +http://dogma.net/markn/articles/zlibtool/zlibtool.htm + +The changes made in version 1.2.2 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory "contrib". + +A Java implementation of zlib is available in the Java Development Kit +http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html +See the zlib home page http://www.zlib.org for details. + +A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is in the +CPAN (Comprehensive Perl Archive Network) sites +http://www.cpan.org/modules/by-module/Compress/ + +A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is +available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html + +A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com> is +availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant <info@winimage.com>, is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + +- When building a shared, i.e. dynamic library on Mac OS X, the library must be + installed before testing (do "make install" before "make test"), since the + library location is specified in the library. + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2004 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. Please +read the FAQ for more information on the distribution of modified source +versions. diff --git a/src/zlib/adler32.c b/src/zlib/adler32.c new file mode 100644 index 000000000..624a1696e --- /dev/null +++ b/src/zlib/adler32.c @@ -0,0 +1,74 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? (int)len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + MOD(s1); + MOD(s2); + } + return (s2 << 16) | s1; +} diff --git a/src/zlib/compress.c b/src/zlib/compress.c new file mode 100644 index 000000000..24ef02919 --- /dev/null +++ b/src/zlib/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/src/zlib/crc32.c b/src/zlib/crc32.c new file mode 100644 index 000000000..b39c7e125 --- /dev/null +++ b/src/zlib/crc32.c @@ -0,0 +1,333 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results about a factor + * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include <stdio.h> +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include <limits.h> +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ diff --git a/src/zlib/crc32.h b/src/zlib/crc32.h new file mode 100644 index 000000000..8053b6117 --- /dev/null +++ b/src/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/src/zlib/deflate.c b/src/zlib/deflate.c new file mode 100644 index 000000000..0fc53bc1e --- /dev/null +++ b/src/zlib/deflate.c @@ -0,0 +1,1502 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2004 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.2 Copyright 1995-2004 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, 255); + s->status = BUSY_STATE; + strm->adler = crc32(0L, Z_NULL, 0); + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy < Z_HUFFMAN_ONLY) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ diff --git a/src/zlib/deflate.h b/src/zlib/deflate.h new file mode 100644 index 000000000..410681d18 --- /dev/null +++ b/src/zlib/deflate.h @@ -0,0 +1,325 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/src/zlib/inffast.c b/src/zlib/inffast.c new file mode 100644 index 000000000..8c02a178d --- /dev/null +++ b/src/zlib/inffast.c @@ -0,0 +1,305 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/src/zlib/inffast.h b/src/zlib/inffast.h new file mode 100644 index 000000000..1e88d2d97 --- /dev/null +++ b/src/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/src/zlib/inffixed.h b/src/zlib/inffixed.h new file mode 100644 index 000000000..75ed4b597 --- /dev/null +++ b/src/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/src/zlib/inflate.c b/src/zlib/inflate.c new file mode 100644 index 000000000..c6d38266d --- /dev/null +++ b/src/zlib/inflate.c @@ -0,0 +1,1274 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->wsize = 0; + state->whave = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include <stdio.h> + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + if (BITS(4) + 8 > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->mode != DICT) return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) return Z_DATA_ERROR; + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + *dest = *source; + *copy = *state; + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) + zmemcpy(window, state->window, 1U << state->wbits); + copy->window = window; + dest->state = (voidpf)copy; + return Z_OK; +} diff --git a/src/zlib/inflate.h b/src/zlib/inflate.h new file mode 100644 index 000000000..9a12c8fd2 --- /dev/null +++ b/src/zlib/inflate.h @@ -0,0 +1,117 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ +#ifdef GUNZIP + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ +#endif + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ +#ifdef GUNZIP + LENGTH, /* i: waiting for 32-bit length (gzip) */ +#endif + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/src/zlib/inftrees.c b/src/zlib/inftrees.c new file mode 100644 index 000000000..8a896b287 --- /dev/null +++ b/src/zlib/inftrees.c @@ -0,0 +1,328 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.2 Copyright 1995-2004 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 198}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)1; + this.val = (unsigned short)0; + *(*table)++ = this; /* make a table to force an error */ + *(*table)++ = this; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || (codes - count[0] != 1))) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += 1U << curr; + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/src/zlib/inftrees.h b/src/zlib/inftrees.h new file mode 100644 index 000000000..82d365a7e --- /dev/null +++ b/src/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 code structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 1440 +#define MAXD 154 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/src/zlib/trees.c b/src/zlib/trees.c new file mode 100644 index 000000000..52c820fa2 --- /dev/null +++ b/src/zlib/trees.c @@ -0,0 +1,1215 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2003 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include <ctype.h> +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1<<extra_lbits[code]); n++) { + _length_code[length++] = (uch)code; + } + } + Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length-1] = (uch)code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<<extra_dbits[code]); n++) { + _dist_code[dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include <stdio.h> +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, + "inconsistent bit counts"); + Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n].Len; + if (len == 0) continue; + /* Now reverse the bits */ + tree[n].Code = bi_reverse(next_code[len]++, len); + + Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", + n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); + } +} + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +local void build_tree(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->strm->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->strm->data_type = bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/src/zlib/trees.h b/src/zlib/trees.h new file mode 100644 index 000000000..72facf900 --- /dev/null +++ b/src/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/src/zlib/zconf.h b/src/zlib/zconf.h new file mode 100644 index 000000000..3c21403fc --- /dev/null +++ b/src/zlib/zconf.h @@ -0,0 +1,326 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2004 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include <windows.h> + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include <sys/types.h> /* for off_t */ +# include <unistd.h> /* for SEEK_* and off_t */ +# ifdef VMS +# include <unixio.h> /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/src/zlib/zlib.h b/src/zlib/zlib.h new file mode 100644 index 000000000..b4ddd3439 --- /dev/null +++ b/src/zlib/zlib.h @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.2, October 3rd, 2004 + + Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.2" +#define ZLIB_VERNUM 0x1220 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR. If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/src/zlib/zutil.c b/src/zlib/zutil.c new file mode 100644 index 000000000..0ef4f99f5 --- /dev/null +++ b/src/zlib/zutil.c @@ -0,0 +1,319 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1 << 16; +#endif +#ifdef NO_GZIP + flags += 1 << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1 << 20; +#endif +#ifdef FASTEST + flags += 1 << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1 << 25; +# ifdef HAS_vsprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1 << 26; +# endif +# endif +#else + flags += 1 << 24; +# ifdef NO_snprintf + flags += 1 << 25; +# ifdef HAS_sprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1 << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* does not exist on WCE */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/src/zlib/zutil.h b/src/zlib/zutil.h new file mode 100644 index 000000000..7b42edcaa --- /dev/null +++ b/src/zlib/zutil.h @@ -0,0 +1,263 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# include <stddef.h> +# include <string.h> +# include <stdlib.h> +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include <errno.h> +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include <alloc.h> +# endif +# else /* MSC or DJGPP */ +# include <malloc.h> +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include <unix.h> /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#ifdef HAVE_STRERROR +# ifndef VMS + extern char *strerror OF((int)); +# endif +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include <stdio.h> + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ |